blob: a947a7488d2d1bf558dc312a868ef4fb813d2bbd [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2* All Rights Reserved
3*
4* MARVELL CONFIDENTIAL
5* Copyright 2012 Marvell International Ltd All Rights Reserved.
6* The source code contained or described herein and all documents related to
7* the source code ("Material") are owned by Marvell International Ltd or its
8* suppliers or licensors. Title to the Material remains with Marvell International Ltd
9* or its suppliers and licensors. The Material contains trade secrets and
10* proprietary and confidential information of Marvell or its suppliers and
11* licensors. The Material is protected by worldwide copyright and trade secret
12* laws and treaty provisions. No part of the Material may be used, copied,
13* reproduced, modified, published, uploaded, posted, transmitted, distributed,
14* or disclosed in any way without Marvell's prior express written permission.
15*
16* No license under any patent, copyright, trade secret or other intellectual
17* property right is granted to or conferred upon you by disclosure or delivery
18* of the Materials, either expressly, by implication, inducement, estoppel or
19* otherwise. Any license under such intellectual property rights must be
20* express and approved by Marvell in writing.
21*
22*/
23
24#define LOG_TAG "acm_aph"
25#define LOG_NDEBUG 0
26
27#include <stdio.h>
28#include <unistd.h> //usleep
29#include <cutils/properties.h>
30#include <stdlib.h>
31#include <cutils/log.h>
32#include "acm_aph.h"
33#include "acm_param.h"
34#include <stdlib.h>
35
36#ifdef PXA1826_AUDIO
37#include "audio_stub.h"
38#include <sys/ioctl.h>
39#include <fcntl.h>
40#endif
41
42#ifdef TARGET_mmp_asr1901_KSTR901
43#include "audio_dsp.h"
44#include "adsp_ve.h"
45#endif
46
47#include "audioCalibration.h"
48
49//-----------------------------------------------------------------------------
50//Codec Definitions:
51// CODEC_PM812/CODEC_PM805/CODEC_NAU8810/CODEC_ALC5616/CODEC_NONE is defined in openwrt\package\libs\pxa1826_audio
52// CODEC_I2S_MASTER/CODEC_I2S_SLAVE/CODEC_PCM_MASTER/CODEC_PCM_SLAVE is defined in openwrt\package\libs\pxa1826_audio
53//-----------------------------------------------------------------------------
54#if defined(CODEC_PM812)
55//PM812 is connected
56#include "acm_pm812.h"
57static BOOL acm_codec_connected = TRUE;
58#elif defined(CODEC_PM805)
59//PM805 is connected
60#include "acm_pm805.h"
61static BOOL acm_codec_connected = TRUE;
62#elif defined(CODEC_NAU8810)
63//NAU8810 is connected
64#include "acm_nau8810.h"
65static BOOL acm_codec_connected = TRUE;
66#elif defined(CODEC_ALC5616)
67//ALC5616 is connected
68#include "acm_alc5616.h"
69static BOOL acm_codec_connected = TRUE;
70#else
71//No codec is connected
72static BOOL acm_codec_connected = FALSE;
73static ACMAPH_Component ACM_Enable[APH_PATH_ID_CNT]={};
74static ACMAPH_Component ACM_Disable[APH_PATH_ID_CNT]={};
75static ACMAPH_Component ACM_Mute[APH_PATH_IN_CNT]={};
76static ACMAPH_Component ACM_UnMute[APH_PATH_IN_CNT]={};
77static ACMAPH_VolumeComponent ACM_Volume[APH_PATH_OUT_CNT]={};
78static APH_ACHComponent ACH_component_table[AUDIO_COMPONENT_CNT]={};
79//Sorted as APH_AudioComponent
80static char APH_AudioComponent_Name[AUDIO_COMPONENT_CNT][16]= {} ;
81#endif
82
83
84//--------------------------------------------------------------
85//-------- Global Information Tables
86//--------------------------------------------------------------
87
88static int modem_is_wb = 0, modem_is_master = 0;
89
90const ACMAPH_AudioPathID AUDIO_PATH_ID_MAPPING[APH_PATH_ID_CNT] = {
91 {APH_PATH_ID_HIFIPLAYTOEARPHONE, "HiFiPlayToEarphone" },
92 {APH_PATH_ID_HIFIPLAYTOSPKR, "HiFiPlayToSPKR" },
93 {APH_PATH_ID_HIFIPLAYTOHP, "HiFiPlayToHP" },
94 {APH_PATH_ID_HIFIRECORDFROMMIC1, "HiFiRecordFromMic1" },
95 {APH_PATH_ID_HIFIRECORDFROMHSMIC, "HiFiRecordFromHsMic" },
96 {APH_PATH_ID_VOICEPLAYTOEARPHONE, "VoicePlayToEarphone" },
97 {APH_PATH_ID_VOICEPLAYTOSPKR, "VoicePlayToSPKR" },
98 {APH_PATH_ID_VOICEPLAYTOHP, "VoicePlayToHP" },
99 {APH_PATH_ID_VOICERECORDFROMMIC1, "VoiceRecordFromMic1" },
100 {APH_PATH_ID_VOICERECORDFROMHSMIC, "VoiceRecordFromHsMic"},
101};
102
103APH_PathStatus path_status_table[APH_PATH_ID_CNT] = {
104 {0, 0, 0},
105 {0, 0, 0},
106 {0, 0, 0},
107 {0, 0, 0},
108 {0, 0, 0},
109 {0, 0, 0},
110 {0, 0, 0},
111 {0, 0, 0},
112 {0, 0, 0},
113 {0, 0, 0}
114};
115
116/* 1:on; 0:off */
117static int g_audio_if_debug_mode = 0;
118
119int get_debug_mode(void)
120{
121 return g_audio_if_debug_mode;
122}
123
124void set_debug_mode(int onoff)
125{
126 g_audio_if_debug_mode = onoff;
127}
128
129void configCodecGainfromNVM(APH_AudioComponent Component_NVM, unsigned char Address_NVM, unsigned short Value_NVM);
130extern int NVM_Calibration_IPC(AC_IPC_Package *package);
131
132const ACMAPH_AudioPathID *ACM_GetPathConfigTable() {
133 return AUDIO_PATH_ID_MAPPING ;
134}
135
136void get_pcm_config(int *p_role, int *p_rate)
137{
138 *p_role = modem_is_master;
139 *p_rate = modem_is_wb;
140 return;
141}
142
143void set_pcm_config(int role, int rate)
144{
145 modem_is_master = role;
146 modem_is_wb = rate;
147
148#if defined(CODEC_ALC5616)
149#ifdef TARGET_mmp_asr1901_KSTR901
150 if (3 == modem_is_wb) {
151 LOGI(set_pcm_config, "%s: modem switch to 48KHz for ALC5616 in Kestrel.", __FUNCTION__);
152 system("echo 3 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616_switch_rate");
153 } else if (2 == modem_is_wb){
154 LOGI(set_pcm_config, "%s: modem switch to 32KHz for ALC5616 in Kestrel.", __FUNCTION__);
155 system("echo 2 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616_switch_rate");
156 } else if (1 == modem_is_wb) {
157 LOGI(set_pcm_config, "%s: modem switch to WB for ALC5616 in Kestrel.", __FUNCTION__);
158 system("echo 1 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616_switch_rate");
159 } else if (0 == modem_is_wb) {
160 LOGI(set_pcm_config, "%s: modem switch to NB for ALC5616 in Kestrel.", __FUNCTION__);
161 system("echo 0 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616_switch_rate");
162 } else {
163 LOGI(set_pcm_config, "%s: modem switch to NB for ALC5616 in Kestrel.", __FUNCTION__);
164 system("echo 0 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616_switch_rate");
165 }
166#else
167 if (1 == modem_is_wb) {
168 LOGI(set_pcm_config, "%s: modem switch to WB for ALC5616.", __FUNCTION__);
169 system("echo 1 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616_switch_rate");
170 } else {
171 LOGI(set_pcm_config, "%s: modem switch to NB for ALC5616.", __FUNCTION__);
172 system("echo 0 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616_switch_rate");
173 }
174#endif
175#endif
176
177 LOGI(set_pcm_config, "%s: modem_is_master=%s, modem_is_wb=%s.", __FUNCTION__, modem_is_master?"TRUE":"FALSE", modem_is_wb?"WB":"NB");
178 return;
179}
180
181static int _get_path_id(const char *path) {
182 const ACMAPH_AudioPathID *ptr;
183 const char *PathName;
184 unsigned int i = 0, size;
185
186 if(path == NULL)
187 return INVALID_PATH_ID;
188
189 size = sizeof(AUDIO_PATH_ID_MAPPING)/sizeof(ACMAPH_AudioPathID);
190 ptr = &AUDIO_PATH_ID_MAPPING[0];
191 while (i < size) {
192 PathName = ptr->PathName;
193 if (strcmp((const char *)path, (const char *)PathName) == 0) {
194 LOGI(_get_path_id, "%s: path=%s, PathName=%s,PathID=%d, i=%d", __FUNCTION__, path, PathName,ptr->PathID, i);
195 return ptr->PathID;
196 }
197
198 ptr++;
199 i++;
200 }
201
202 return INVALID_PATH_ID;
203}
204
205static ACMAPH_Component *_get_APHTable(APH_PATH_ID path_id, ACMAPH_Component *pTable, unsigned char max) {
206 int i = 0;
207
208 for (i = 0; i < max; i++) {
209 if (pTable[i].PathID == path_id) {
210 LOGI(_get_APHTable, "%s: path_id=%d", __FUNCTION__, path_id);
211 return &pTable[i];
212 }
213 }
214
215 return NULL;
216}
217
218#if !defined(CODEC_PM805) && !defined(CODEC_PM812) && !defined(CODEC_NAU8810) && !defined(CODEC_ALC5616)
219static ACMAPH_VolumeComponent *_get_APHVolumeTable(APH_PATH_ID path_id, ACMAPH_VolumeComponent *pTable, unsigned char max) {
220 int i = 0;
221
222 for (i = 0; i < max; i++) {
223 if (pTable[i].PathID == path_id) {
224 LOGI(_get_APHVolumeTable, "%s: path_id=%d", __FUNCTION__, path_id);
225 return &pTable[i];
226 }
227 }
228
229 return NULL;
230}
231#endif
232
233static ACH_ComponentHandler *_get_component_handler(APH_AudioComponent component_id) {
234 int size = sizeof(ACH_component_table) / sizeof(ACH_component_table[0]);
235 int i = 0;
236
237 for (i = 0; i < size; i++) {
238 if (ACH_component_table[i].component_id == component_id) {
239 LOGI(_get_component_handler, "%s: component_id=%d", __FUNCTION__, component_id);
240 return ACH_component_table[i].component_handler;
241 }
242 }
243
244 return NULL;
245}
246
247static void _reset_components_registers() {
248 int size = sizeof(ACH_component_table) / sizeof(ACH_component_table[0]);
249 int i = 0;
250
251 /* Disable all components when init.*/
252 for (i = 0; i < size; i++) {
253 if (ACH_component_table[i].component_handler) {
254 ACH_component_table[i].component_handler->ACH_Reset();
255 }
256 }
257}
258
259static void _reset_components_status() {
260 int size = sizeof(ACH_component_table) / sizeof(ACH_component_table[0]);
261 int i = 0;
262
263 for (i = 0; i < size; i++) {
264 ACH_component_table[i].component_handler->active = COMPONENT_INACTIVE;
265 ACH_component_table[i].component_handler->ref_count = 0;
266 }
267
268 /* Disable all components when init.*/
269 for (i = 0; i < size; i++) {
270 ACH_component_table[i].component_handler->ACH_Disable();
271 }
272}
273
274static ACM_ReturnCode _get_path_direction(const char *path, unsigned char *path_direction) {
275 ACM_ReturnCode ret = ACM_RC_INVALID_PARAMETER;
276 if(path != NULL) {
277 if(strstr((const char *)path, "PlayTo") != NULL) {
278 *path_direction = PATH_DIRECTION_OUT;
279 ret = ACM_RC_OK;
280 }
281 if(strstr((const char *)path, "RecordFrom") != NULL) {
282 *path_direction = PATH_DIRECTION_IN;
283 ret = ACM_RC_OK;
284 }
285 }
286 return ret;
287}
288
289char * ACM_GetPathName(int PathID) {
290 const ACMAPH_AudioPathID *ptr;
291 unsigned int i = 0, size;
292
293 if(PathID >= APH_PATH_ID_CNT) {
294 return NULL;
295 }
296
297 size = sizeof(AUDIO_PATH_ID_MAPPING)/sizeof(ACMAPH_AudioPathID);
298 ptr = &AUDIO_PATH_ID_MAPPING[0];
299 while (i < size) {
300 if (PathID == ptr->PathID) {
301 LOGI(_get_PathName, "%s: PathName=%s, PathID=%d, i=%d", __FUNCTION__, ptr->PathName,ptr->PathID, i);
302 return ptr->PathName;
303 }
304
305 ptr++;
306 i++;
307 }
308
309 return NULL;
310}
311
312ACM_ReturnCode APHAudioPathEnable(const char * path, unsigned int value) {
313 int path_id = INVALID_PATH_ID;
314 APH_AudioComponent component;
315 ACMAPH_Register *RegisterList;
316 unsigned int i, size;
317 ACH_ComponentParameter param;
318 ACH_ComponentHandler *component_handler = NULL;
319 ACMAPH_Component *pTable = NULL;
320
321 LOGI(APHAudioPathEnable, "%s/L%d: modem_is_wb=%d, modem_is_master=%d, value=0x%x", __FUNCTION__, __LINE__, modem_is_wb, modem_is_master, value);
322
323 if(acm_codec_connected == TRUE){
324 LOGI(APHAudioPathEnable, "%s/L%d: path=%s, value=0x%x", __FUNCTION__, __LINE__, path, value);
325 }
326 else {
327 LOGE(APHAudioPathEnable, "%s/L%d: path=%s, no codec connected!", __FUNCTION__, __LINE__, path);
328 return ACM_RC_INVALID_PARAMETER;
329 }
330
331 path_id = _get_path_id(path);
332 if(path_id == INVALID_PATH_ID){
333 LOGE(APHAudioPathEnable, "%s/L%d: Error path_id=%d", __FUNCTION__, __LINE__, path_id);
334 return ACM_RC_INVALID_PATH;
335 }
336
337 pTable = _get_APHTable(path_id, ACM_Enable, APH_PATH_ID_CNT);
338 if(pTable == NULL){
339 LOGE(APHAudioPathEnable, "%s/L%d: Error pTable=%d", __FUNCTION__, __LINE__, pTable);
340 return ACM_RC_INVALID_PATH;
341 }
342
343 if(path_status_table[path_id].enabled != 0){
344 LOGE(APHAudioPathEnable, "%s/L%d: Already enable path %s(%d)", __FUNCTION__, __LINE__, path, path_id);
345 return ACM_RC_PATH_ALREADY_ENABLED;
346 }
347 else{
348 path_status_table[path_id].enabled = 1;
349 }
350
351 size = pTable->RegisterNum;
352 RegisterList = pTable->RegisterList;
353
354 for(i = 0; i < size; i++){
355 // get matched component
356 component = RegisterList[i].Component;
357 if(component == DELAY){
358 usleep(RegisterList[i].Value * 1000);
359 continue;
360 }
361
362 if(_get_component_handler(component) != component_handler ){
363 component_handler = _get_component_handler(component);
364
365 ///update component_handler-->ref_count: it depends on registers sorting style
366 component_handler->ref_count++;
367 LOGI(APHAudioPathEnable, "%s/L%d: component=%s, ref_count=%d", __FUNCTION__, __LINE__, APH_AudioComponent_Name[component], component_handler->ref_count);
368 }
369
370 //firstly enable component
371 if(component_handler->active == COMPONENT_INACTIVE){
372 component_handler->ACH_Enable();
373 component_handler->active = COMPONENT_ACTIVE;
374 }
375
376 /*
377 * Set value according to modem_is_wb & modem_is_master
378 *
379 */
380 //The registers of PM812 are identical with PM805
381#if defined(CODEC_PM812)
382 if( RegisterList[i].Address == CODEC_PM812_VOICE_REG35){
383 LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_master?"master":"slave");
384 if (1 == modem_is_master)
385 RegisterList[i].Value = CODEC_PM812_VOICE_SLAVE;
386 else
387 RegisterList[i].Value = CODEC_PM812_VOICE_MASTER;
388 }
389
390 if( RegisterList[i].Address == CODEC_PM812_VOICE_REG36){
391 LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_wb?"16KHz":"8KHz");
392 if (1 == modem_is_wb)
393 RegisterList[i].Value = CODEC_PM812_VOICE_WB;
394 else
395 RegisterList[i].Value = CODEC_PM812_VOICE_NB;
396 }
397#elif defined(CODEC_PM805)
398 if( RegisterList[i].Address == CODEC_PM805_AUDIO_REG30){
399 #if defined(CODEC_I2S_MASTER)
400 RegisterList[i].Value = CODEC_PM805_AUDIO_MASTER;
401 LOGI(APHAudioPathEnable, "%s/L%d: CODEC_PM805_AUDIO_MASTER.", __FUNCTION__, __LINE__);
402 #endif
403
404 #if defined(CODEC_I2S_SLAVE)
405 RegisterList[i].Value = CODEC_PM805_AUDIO_SLAVE;
406 LOGI(APHAudioPathEnable, "%s/L%d: CODEC_PM805_AUDIO_SLAVE.", __FUNCTION__, __LINE__);
407 #endif
408 }
409
410 if( RegisterList[i].Address == CODEC_PM805_VOICE_REG35){
411 LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_master?"master":"slave");
412 if (1 == modem_is_master)
413 RegisterList[i].Value = CODEC_PM805_VOICE_SLAVE;
414 else
415 RegisterList[i].Value = CODEC_PM805_VOICE_MASTER;
416 }
417
418 if( RegisterList[i].Address == CODEC_PM805_VOICE_REG36){
419 LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_wb?"16KHz":"8KHz");
420 if (1 == modem_is_wb)
421 RegisterList[i].Value = CODEC_PM805_VOICE_WB;
422 else
423 RegisterList[i].Value = CODEC_PM805_VOICE_NB;
424 }
425#elif defined(CODEC_NAU8810)
426 if( RegisterList[i].Address == CODEC_NAU8810_VOICE_REG06){
427 LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_master?"master":"slave");
428 if (1 == modem_is_master)
429 RegisterList[i].Value = CODEC_NAU8810_VOICE_SLAVE;
430 else
431 RegisterList[i].Value = CODEC_NAU8810_VOICE_MASTER;
432 }
433
434 if( RegisterList[i].Address == CODEC_NAU8810_VOICE_REG07){
435 LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_wb?"16KHz":"8KHz");
436 if (1 == modem_is_wb)
437 RegisterList[i].Value = CODEC_NAU8810_VOICE_WB;
438 else
439 RegisterList[i].Value = CODEC_NAU8810_VOICE_NB;
440 }
441#elif defined(CODEC_ALC5616)
442 if( RegisterList[i].Address == CODEC_ALC5616_VOICE_REG70){
443 LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_master?"master":"slave");
444 if (1 == modem_is_master)
445 RegisterList[i].Value = CODEC_ALC5616_VOICE_SLAVE;
446 else
447 RegisterList[i].Value = CODEC_ALC5616_VOICE_MASTER;
448 }
449
450 //WB/NB is set in kernel file driver/mfd/alc5616.c.
451#endif
452 //fill param
453 param.i2c.reg_index = RegisterList[i].Address;
454 param.i2c.reg_value = &RegisterList[i].Value;
455 param.i2c.reg_mask = 0xffff;
456 param.i2c.reg_shift = 0;
457 param.i2c.length = sizeof(short);
458
459 //configure component
460 component_handler->ACH_Handle(&param);
461 }
462
463 return ACM_RC_OK;
464}
465
466ACM_ReturnCode APHAudioPathDisable(const char * path) {
467 int path_id = INVALID_PATH_ID;
468 APH_AudioComponent component;
469 ACMAPH_Register *RegisterList;
470 unsigned int i, size;
471 ACH_ComponentParameter param;
472 ACH_ComponentHandler *component_handler = NULL;
473 ACMAPH_Component *pTable = NULL;
474
475 if(acm_codec_connected == TRUE){
476 LOGI(APHAudioPathDisable, "%s/L%d: path=%s", __FUNCTION__, __LINE__, path);
477 }
478 else {
479 LOGE(APHAudioPathDisable, "%s/L%d: path=%s, no codec connected!", __FUNCTION__, __LINE__, path);
480 return ACM_RC_INVALID_PARAMETER;
481 }
482
483 path_id = _get_path_id(path);
484 if(path_id == INVALID_PATH_ID){
485 LOGE(APHAudioPathDisable, "%s/L%d: Error path_id=%d", __FUNCTION__, __LINE__, path_id);
486 return ACM_RC_INVALID_PATH;
487 }
488
489 pTable = _get_APHTable(path_id, ACM_Disable, APH_PATH_ID_CNT);
490 if(pTable == NULL){
491 LOGE(APHAudioPathDisable, "%s/L%d: Error pTable=%d", __FUNCTION__, __LINE__, pTable);
492 return ACM_RC_INVALID_PATH;
493 }
494
495 if(path_status_table[path_id].enabled == 0){
496 LOGE(APHAudioPathDisable, "%s/L%d: Already disable path %s(%d)", __FUNCTION__, __LINE__, path, path_id);
497 return ACM_RC_PATH_ALREADY_DISABLED;
498 }
499 else{
500 path_status_table[path_id].enabled = 0;
501 ////path_status_table[path_id].value = 0; // Save volume even after disabled
502 path_status_table[path_id].mute = 0;
503 }
504
505 size = pTable->RegisterNum;
506 RegisterList = pTable->RegisterList;
507
508 for(i = 0; i < size; i++){
509 // get matched component
510 component = RegisterList[i].Component;
511 if(component == DELAY){
512 usleep(RegisterList[i].Value * 1000);
513 continue;
514 }
515
516 if(_get_component_handler(component) != component_handler ){
517 component_handler = _get_component_handler(component);
518
519 ///update component_handler-->ref_count: it depends on registers sorting style
520 component_handler->ref_count--;
521 LOGI(APHAudioPathDisable, "%s/L%d: component=%s, ref_count=%d", __FUNCTION__, __LINE__, APH_AudioComponent_Name[component], component_handler->ref_count);
522 }
523
524 //fill param
525 param.i2c.reg_index = RegisterList[i].Address;
526 param.i2c.reg_value = &RegisterList[i].Value;
527 param.i2c.reg_mask = 0xffff;
528 param.i2c.reg_shift = 0;
529 param.i2c.length = sizeof(short);
530
531 //configure component
532 component_handler->ACH_Handle(&param);
533
534 //Last: if this component is not referred anymore,disable component
535 if(component_handler->ref_count == 0){
536 if(component_handler->active == COMPONENT_ACTIVE){
537 component_handler->ACH_Disable();
538 component_handler->active = COMPONENT_INACTIVE;
539 }
540 }
541 }
542
543 return ACM_RC_OK;
544}
545
546ACM_ReturnCode APHAudioPathCheckPathId (int path_id_Rx, int path_id_Tx) {
547
548 if ((path_id_Rx == INVALID_PATH_ID) || (path_id_Tx == INVALID_PATH_ID))
549 {
550 LOGE(APHAudioPathCheckPathId, "%s/L%d: Error", __FUNCTION__, __LINE__);
551 return ACM_RC_INVALID_PATH;
552 }
553
554 if (((APH_PATH_ID_HIFIPLAYTOEARPHONE == path_id_Rx) ||(APH_PATH_ID_HIFIPLAYTOSPKR == path_id_Rx))
555 && (APH_PATH_ID_HIFIRECORDFROMMIC1 == path_id_Tx))
556 {
557 return ACM_RC_OK_HIFI_MATCHED;
558 }
559 else if ((APH_PATH_ID_HIFIPLAYTOHP == path_id_Rx) && (APH_PATH_ID_HIFIRECORDFROMHSMIC == path_id_Tx))
560 {
561 return ACM_RC_OK_HIFI_MATCHED;
562 }
563 else if (((APH_PATH_ID_VOICEPLAYTOEARPHONE == path_id_Rx) ||(APH_PATH_ID_VOICEPLAYTOSPKR == path_id_Rx)
564 || (APH_PATH_ID_VOICEPLAYTOHP == path_id_Rx))
565 && (APH_PATH_ID_VOICERECORDFROMMIC1 == path_id_Tx))
566 {
567 return ACM_RC_OK_VOICE_MATCHED;
568 }
569 else if ((APH_PATH_ID_VOICEPLAYTOHP == path_id_Rx) && (APH_PATH_ID_VOICERECORDFROMHSMIC == path_id_Tx))
570 {
571 return ACM_RC_OK_VOICE_MATCHED;
572 }
573 else
574 {
575 return ACM_RC_PATH_CONFIG_NOT_EXIST;
576 }
577
578 return ACM_RC_OK;
579}
580
581ACM_ReturnCode APHAudioPathCheck (const char * path_Rx, const char * path_Tx) {
582
583 int path_id_Rx = INVALID_PATH_ID;
584 int path_id_Tx = INVALID_PATH_ID;
585
586 if ((NULL == path_Rx) || (NULL == path_Tx))
587 {
588 LOGE(APHAudioPathCheck, "%s/L%d: Rx path or Tx path is NULL, please check it.", __FUNCTION__, __LINE__);
589 return ACM_RC_PATH_CONFIG_NOT_EXIST;
590 }
591
592 path_id_Rx = _get_path_id(path_Rx);
593 path_id_Tx = _get_path_id(path_Tx);
594
595 if((path_id_Rx == INVALID_PATH_ID) || (path_id_Tx == INVALID_PATH_ID) )
596 {
597 LOGE(APHAudioPathCheck, "%s/L%d: Error", __FUNCTION__, __LINE__);
598 return ACM_RC_INVALID_PATH;
599 }
600
601 if (((APH_PATH_ID_HIFIPLAYTOEARPHONE == path_id_Rx) ||(APH_PATH_ID_HIFIPLAYTOSPKR == path_id_Rx))
602 && (APH_PATH_ID_HIFIRECORDFROMMIC1 == path_id_Tx))
603 {
604 return ACM_RC_OK_HIFI_MATCHED;
605 }
606 else if ((APH_PATH_ID_HIFIPLAYTOHP == path_id_Rx) && (APH_PATH_ID_HIFIRECORDFROMHSMIC == path_id_Tx))
607 {
608 return ACM_RC_OK_HIFI_MATCHED;
609 }
610 else if (((APH_PATH_ID_VOICEPLAYTOEARPHONE == path_id_Rx) ||(APH_PATH_ID_VOICEPLAYTOSPKR == path_id_Rx)
611 || (APH_PATH_ID_VOICEPLAYTOHP == path_id_Rx))
612 && (APH_PATH_ID_VOICERECORDFROMMIC1 == path_id_Tx))
613 {
614 return ACM_RC_OK_VOICE_MATCHED;
615 }
616 else if ((APH_PATH_ID_VOICEPLAYTOHP == path_id_Rx) && (APH_PATH_ID_VOICERECORDFROMHSMIC == path_id_Tx))
617 {
618 return ACM_RC_OK_VOICE_MATCHED;
619 }
620 else
621 {
622 return ACM_RC_PATH_CONFIG_NOT_EXIST;
623 }
624
625 return ACM_RC_OK;
626}
627
628void APHDisableAllPath(void)
629{
630 int i = 0;
631
632 //disable the enabled path
633 for (i=0; i<APH_PATH_ID_CNT; i++)
634 {
635 //disable the enabled path
636 if ( path_status_table[i].enabled)
637 {
638 LOGI(APHDisableAllPath, "disable the path:%s.......", AUDIO_PATH_ID_MAPPING[i].PathName);
639 ACMAudioPathDisable(AUDIO_PATH_ID_MAPPING[i].PathName);
640 }
641 }
642
643 return;
644}
645
646ACM_ReturnCode APHAudioPathSwitch (const char * path_Rx, const char * path_Tx, unsigned int value) {
647
648 char tmp_buffer[PATHSTATUS_MAX] = {0};
649 int i = 0;
650
651 if ((APHAudioPathCheck(path_Rx, path_Tx) != ACM_RC_OK_HIFI_MATCHED)
652 && (APHAudioPathCheck(path_Rx, path_Tx) != ACM_RC_OK_VOICE_MATCHED))
653 {
654 LOGE(APHAudioPathSwitch, "%s/L%d: Rx path is not matched with Tx path.", __FUNCTION__, __LINE__);
655 return ACM_RC_PATH_CONFIG_NOT_EXIST;
656 }
657
658 if (ACM_GetPathStatus(tmp_buffer, PATHSTATUS_MAX) != ACM_RC_OK)
659 {
660 LOGE(APHAudioPathSwitch, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
661 return ACM_RC_PATH_CONFIG_NOT_EXIST;
662 }
663
664 //before switch, before disable, list the path status
665 LOGI(APHAudioPathSwitch, "before switch, before disable, current every path status is:%s.......", tmp_buffer);
666
667 //disable the enabled path
668 for (i=0; i<APH_PATH_ID_CNT; i++)
669 {
670 //disable the enabled path
671 if ( path_status_table[i].enabled)
672 {
673 LOGI(APHAudioPathSwitch, "disable the path:%s.......", AUDIO_PATH_ID_MAPPING[i].PathName);
674 ACMAudioPathDisable(AUDIO_PATH_ID_MAPPING[i].PathName);
675 }
676 }
677
678 memset(tmp_buffer, 0x00, sizeof(tmp_buffer));
679
680 if (ACM_GetPathStatus(tmp_buffer, PATHSTATUS_MAX) != ACM_RC_OK)
681 {
682 LOGE(APHAudioPathSwitch, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
683 return ACM_RC_PATH_CONFIG_NOT_EXIST;
684 }
685
686 //before switch, after disable, list the path status
687 LOGI(APHAudioPathSwitch, "before switch, after disable, current every path status is:%s.......", tmp_buffer);
688
689 //enable the Rx path, and Tx path
690 ACMAudioPathEnable(path_Rx, value);
691 ACMAudioPathEnable(path_Tx, value);
692
693 memset(tmp_buffer, 0x00, sizeof(tmp_buffer));
694
695 if (ACM_GetPathStatus(tmp_buffer, PATHSTATUS_MAX) != ACM_RC_OK)
696 {
697 LOGE(APHAudioPathSwitch, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
698 return ACM_RC_PATH_CONFIG_NOT_EXIST;
699 }
700
701 //before switch, after disable, list the path status
702 LOGI(APHAudioPathSwitch, "after switch, after disable, current every path status is:%s.......", tmp_buffer);
703
704 return ACM_RC_OK;
705}
706
707ACM_ReturnCode APHAudioPathMute(const char * path, unsigned int value) {
708 int path_id = INVALID_PATH_ID;
709 APH_AudioComponent component;
710 ACMAPH_Register *RegisterList;
711 unsigned int i, size;
712 ACH_ComponentParameter param;
713 ACH_ComponentHandler *component_handler = NULL;
714 ACMAPH_Component *pTable = NULL;
715
716 if(acm_codec_connected == TRUE){
717 LOGI(APHAudioPathMute, "%s/L%d: path=%s, %s", __FUNCTION__, __LINE__, path, value?"Mute":"UnMute");
718 }
719 else {
720 LOGE(APHAudioPathMute, "%s/L%d: path=%s, no codec connected!", __FUNCTION__, __LINE__, path);
721 return ACM_RC_INVALID_PARAMETER;
722 }
723
724 path_id = _get_path_id(path);
725 if(path_id == INVALID_PATH_ID){
726 LOGE(APHAudioPathMute, "%s/L%d: Error path_id=%d", __FUNCTION__, __LINE__, path_id);
727 return ACM_RC_INVALID_PATH;
728 }
729
730 if(value == 0)
731 pTable = _get_APHTable(path_id, ACM_UnMute, APH_PATH_IN_CNT);
732 else
733 pTable = _get_APHTable(path_id, ACM_Mute, APH_PATH_IN_CNT);
734 if(pTable == NULL){
735 LOGE(APHAudioPathMute, "%s/L%d: not in pTable{ACM_Mute,ACM_UnMute}=%d, path=%s", __FUNCTION__, __LINE__, pTable, path);
736 return ACM_RC_INVALID_PATH;
737 }
738
739 if(path_status_table[path_id].enabled == 0){
740 LOGE(APHAudioPathMute, "%s/L%d: Count not operate on disabled path %s(%d)", __FUNCTION__, __LINE__, path, path_id);
741 return ACM_RC_PATH_ALREADY_DISABLED;
742 }
743
744 if(path_status_table[path_id].mute == value){
745 LOGE(APHAudioPathMute, "%s/L%d: path %s(%d) is already %", __FUNCTION__, __LINE__, path, path_id, value?"Mute":"UnMute");
746 return ACM_RC_NO_MUTE_CHANGE_NEEDED;
747 }
748 path_status_table[path_id].mute = value;
749
750 size = pTable->RegisterNum;
751 RegisterList = pTable->RegisterList;
752
753 for(i = 0; i < size; i++){
754 // get matched component
755 component = RegisterList[i].Component;
756 if(component == DELAY){
757 usleep(RegisterList[i].Value * 1000);
758 continue;
759 }
760
761 if(_get_component_handler(component) != component_handler ){
762 component_handler = _get_component_handler(component);
763
764 ///update component_handler-->ref_count: it depends on registers sorting style
765 component_handler->ref_count--;
766 LOGI(APHAudioPathMute, "%s/L%d: component=%s, ref_count=%d", __FUNCTION__, __LINE__, APH_AudioComponent_Name[component], component_handler->ref_count);
767 }
768
769 //fill param
770 param.i2c.reg_index = RegisterList[i].Address;
771 param.i2c.reg_value = &RegisterList[i].Value;
772 param.i2c.reg_mask = 0xffff;
773 param.i2c.reg_shift = 0;
774 param.i2c.length = sizeof(short);
775
776 //configure component
777 component_handler->ACH_Handle(&param);
778 }
779
780 return ACM_RC_OK;
781}
782
783void configCodecGainfromNVM(APH_AudioComponent Component_NVM, unsigned char Address_NVM, unsigned short Value_NVM)
784{
785 ACH_ComponentHandler *component_handler = NULL;
786 APH_AudioComponent component;
787 ACH_ComponentParameter param;
788
789 LOGI(configCodecGainfromNVM,"%s/L%d:: Component=[%d], Address_NVM=[0X%x], Value_NVM=[0X%x] !",
790 __FUNCTION__, __LINE__, Component_NVM, Address_NVM, Value_NVM);
791
792 //if(volume == RegisterList[i].Volume ){
793 // get matched component
794 component = Component_NVM;
795 //component = RegisterList[i].Component;
796 if(component == DELAY)
797 {
798 //usleep(RegisterList[i].Value * 1000);
799 usleep(Value_NVM * 1000);
800 return;
801 }
802
803 if(_get_component_handler(component) != component_handler )
804 {
805 component_handler = _get_component_handler(component);
806
807 ///update component_handler-->ref_count: it depends on registers sorting style
808 component_handler->ref_count--;
809 LOGI(configCodecGainfromNVM, "%s/L%d: component=%s, ref_count=%d", __FUNCTION__, __LINE__, APH_AudioComponent_Name[component], component_handler->ref_count);
810 }
811
812 //fill param
813 param.i2c.reg_index = Address_NVM;
814 param.i2c.reg_value = &Value_NVM;
815 param.i2c.reg_mask = 0xffff;
816 param.i2c.reg_shift = 0;
817 param.i2c.length = sizeof(short);
818
819 LOGI(configCodecGainfromNVM,"%s/L%d:: Address = 0X%x, .Value=0X%x!", __FUNCTION__, __LINE__, Address_NVM, Value_NVM);
820
821 //configure component
822 component_handler->ACH_Handle(&param);
823
824 return;
825}
826
827ACM_ReturnCode APHAudioPathVolumeSet(const char * path, unsigned int value) {
828 int path_id = INVALID_PATH_ID;
829 unsigned char volume = 0;
830 unsigned int i;
831 unsigned char index_volume = 0;
832
833#if defined(CODEC_PM805) || defined(CODEC_PM812) || defined(CODEC_NAU8810) || defined(CODEC_ALC5616)
834 AC_IPC_Package package;
835 ACMCodec_GainT buffer;
836 AUDIO_PROFILE_ID cur_Profile_id = HIFI_HANDSET;
837
838 APH_AudioComponent Component_NVM;
839 unsigned char Address_NVM;
840 unsigned short Value_NVM;
841
842 memset(&package, 0x00, sizeof(AC_IPC_Package));
843 memset(&buffer, 0x00, sizeof(ACMCodec_GainT));
844#else
845 ACMAPH_VolumeComponent *pTable = NULL;
846#endif
847
848 if(acm_codec_connected == TRUE){
849 LOGI(APHAudioPathVolumeSet, "%s/L%d: path=%s, value=0x%x", __FUNCTION__, __LINE__, path, value);
850 }
851 else {
852 LOGE(APHAudioPathVolumeSet, "%s/L%d: path=%s, no codec connected!", __FUNCTION__, __LINE__, path);
853 return ACM_RC_INVALID_PARAMETER;
854 }
855
856 path_id = _get_path_id(path);
857 if(path_id == INVALID_PATH_ID){
858 LOGE(APHAudioPathVolumeSet, "%s/L%d: Error path_id=%d", __FUNCTION__, __LINE__, path_id);
859 return ACM_RC_INVALID_PATH;
860 }
861
862#if defined(CODEC_PM805) || defined(CODEC_PM812) || defined(CODEC_NAU8810) || defined(CODEC_ALC5616)
863 if ((APH_PATH_ID_HIFIRECORDFROMMIC1 == path_id) || (APH_PATH_ID_HIFIRECORDFROMHSMIC == path_id)
864 || (APH_PATH_ID_VOICERECORDFROMMIC1 == path_id) ||(APH_PATH_ID_VOICERECORDFROMHSMIC == path_id))
865 {
866 LOGI(APHAudioPathVolumeSet, "===%s/L%d: PATH ID=%d, no need to config Tx gain! ===", __FUNCTION__, __LINE__, path_id);
867 return ACM_RC_OK;
868 }
869
870 //RX path is mapping to PROFILE.
871 switch (path_id)
872 {
873 case APH_PATH_ID_HIFIPLAYTOEARPHONE:
874 cur_Profile_id = HIFI_HANDSET;
875 break;
876
877 case APH_PATH_ID_HIFIPLAYTOSPKR:
878 cur_Profile_id = HIFI_SPEAKER;
879 break;
880
881 case APH_PATH_ID_HIFIPLAYTOHP:
882 cur_Profile_id = HIFI_HEADSET;
883 break;
884
885 case APH_PATH_ID_VOICEPLAYTOEARPHONE:
886 cur_Profile_id = VC_HANDSET;
887 break;
888
889 case APH_PATH_ID_VOICEPLAYTOSPKR:
890 cur_Profile_id = VC_HANDSFREE;
891 break;
892
893 case APH_PATH_ID_VOICEPLAYTOHP:
894 cur_Profile_id = VC_HEADSET;
895 break;
896
897 default:
898 LOGI(APHAudioPathVolumeSet, "%s/L%d: PATH ID=%d, PATH is %s.", __FUNCTION__, __LINE__, path_id, path);
899 break;
900 }
901
902 package.type = AUDIO_NVM_GetGainConfigure;
903 package.body.d1 = 0;
904 package.body.d2 = cur_Profile_id; //path ID (unsigned short)
905 package.ptr = &buffer;
906
907 NVM_Calibration_IPC(&package);
908
909 LOGI(APHAudioPathVolumeSet,"APHAudioPathVolumeSet:: profile=%d, Tx_DSPGain=%d, sizeof(AUDIO_PROFILE_ID)=%d!",
910 buffer.Profile_id, buffer.Tx_DSPGain, sizeof(AUDIO_PROFILE_ID));
911
912 for (i=0; i<AUDIOHAL_SPK_VOL_QTY; i++)
913 {
914 LOGI(APHAudioPathVolumeSet,"Rx_CodecGain[%d]:: Component_1=0x%x, RegAddr_1=0x%x, RegVal_1=0x%x !",
915 i, buffer.Rx_CodecGain[i].Component_1, buffer.Rx_CodecGain[i].RegAddr_1, buffer.Rx_CodecGain[i].RegVal_1);
916
917 LOGI(APHAudioPathVolumeSet,"Rx_CodecGain[%d]:: Component_2=0x%x, RegAddr_2=0x%x, RegVal_2=0x%x !",
918 i, buffer.Rx_CodecGain[i].Component_2, buffer.Rx_CodecGain[i].RegAddr_2, buffer.Rx_CodecGain[i].RegVal_2);
919
920 LOGI(APHAudioPathVolumeSet,"Rx_CodecGain[%d]:: Component_3=0x%x, RegAddr_3=0x%x, RegVal_3=0x%x !\n",
921 i, buffer.Rx_CodecGain[i].Component_3, buffer.Rx_CodecGain[i].RegAddr_3, buffer.Rx_CodecGain[i].RegVal_3);
922
923 LOGI(APHAudioPathVolumeSet,"Rx_CodecGain[%d]:: Component_4=0x%x, RegAddr_4=0x%x, RegVal_4=0x%x !\n",
924 i, buffer.Rx_CodecGain[i].Component_4, buffer.Rx_CodecGain[i].RegAddr_4, buffer.Rx_CodecGain[i].RegVal_4);
925 }
926
927#endif
928
929#if !defined(CODEC_PM805) && !defined(CODEC_PM812) && !defined(CODEC_NAU8810) && !defined(CODEC_ALC5616)
930 pTable = _get_APHVolumeTable(path_id, ACM_Volume, APH_PATH_OUT_CNT);
931 if(pTable == NULL){
932 LOGE(APHAudioPathVolumeSet, "%s/L%d: Error pTable=%d", __FUNCTION__, __LINE__, pTable);
933 return ACM_RC_INVALID_PATH;
934 }
935#endif
936
937 if(path_status_table[path_id].enabled == 0){
938 LOGE(APHAudioPathVolumeSet, "%s/L%d: Path %s(%d) is not enabled", __FUNCTION__, __LINE__, path, path_id);
939 return ACM_RC_PATH_NOT_ENABLED;
940 }
941
942 if(path_status_table[path_id].value == value){
943 LOGE(APHAudioPathVolumeSet, "%s/L%d: Path %s(%d), value=%d.", __FUNCTION__, __LINE__, path, path_id, value);
944 /* when modify the value of NVM and reload the modification, need to complete the following procedure. */
945 //return ACM_RC_INVALID_VOLUME_CHANGE;
946 }
947
948 LOGI(APHAudioPathVolumeSet,"%s/L%d:: path_status_table[%d].value = %d!", __FUNCTION__, __LINE__, path_id, path_status_table[path_id].value);
949
950 path_status_table[path_id].value = value;
951 volume = (unsigned char)(value & VOLUME_MASK);
952 volume = (volume + 5) /10;
953 index_volume = volume;
954 volume *= 10;
955
956 LOGI(APHAudioPathVolumeSet,"%s/L%d:: volume = %d!", __FUNCTION__, __LINE__, volume);
957
958 if (volume > MAX_VOLUME_INDEX) {
959 LOGE(APHAudioPathVolumeSet,"%s/L%d:: too big volume = %d!", __FUNCTION__, __LINE__, volume);
960 return ACM_RC_INVALID_VOLUME_CHANGE;
961 }
962
963#if defined(CODEC_PM805) || defined(CODEC_PM812) || defined(CODEC_NAU8810) || defined(CODEC_ALC5616)
964
965 if (0xFFFF != buffer.Rx_CodecGain[index_volume].RegAddr_1)
966 {
967 Component_NVM = buffer.Rx_CodecGain[index_volume].Component_1;
968 Address_NVM = buffer.Rx_CodecGain[index_volume].RegAddr_1;
969 Value_NVM = buffer.Rx_CodecGain[index_volume].RegVal_1;
970
971 configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
972 }
973
974 if (0xFFFF != buffer.Rx_CodecGain[index_volume].RegAddr_2)
975 {
976 Component_NVM = buffer.Rx_CodecGain[index_volume].Component_2;
977 Address_NVM = buffer.Rx_CodecGain[index_volume].RegAddr_2;
978 Value_NVM = buffer.Rx_CodecGain[index_volume].RegVal_2;
979
980 configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
981 }
982
983 if (0xFFFF != buffer.Rx_CodecGain[index_volume].RegAddr_3)
984 {
985 Component_NVM = buffer.Rx_CodecGain[index_volume].Component_3;
986 Address_NVM = buffer.Rx_CodecGain[index_volume].RegAddr_3;
987 Value_NVM = buffer.Rx_CodecGain[index_volume].RegVal_3;
988
989 configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
990 }
991
992 if (0xFFFF != buffer.Rx_CodecGain[index_volume].RegAddr_4)
993 {
994 Component_NVM = buffer.Rx_CodecGain[index_volume].Component_4;
995 Address_NVM = buffer.Rx_CodecGain[index_volume].RegAddr_4;
996 Value_NVM = buffer.Rx_CodecGain[index_volume].RegVal_4;
997
998 configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
999 }
1000
1001 LOGI(APHAudioPathVolumeSet,"Tx_CodecGain:: Component_1=0x%x, RegAddr_1=0x%x, RegVal_1=0x%x !\n",
1002 buffer.Tx_CodecGain.Component_1, buffer.Tx_CodecGain.RegAddr_1, buffer.Tx_CodecGain.RegVal_1);
1003
1004 LOGI(APHAudioPathVolumeSet,"Tx_CodecGain:: Component_2=0x%x, RegAddr_2=0x%x, RegVal_2=0x%x !\n",
1005 buffer.Tx_CodecGain.Component_2, buffer.Tx_CodecGain.RegAddr_2, buffer.Tx_CodecGain.RegVal_2);
1006
1007 LOGI(APHAudioPathVolumeSet,"Tx_CodecGain:: Component_3=0x%x, RegAddr_3=0x%x, RegVal_3=0x%x !\n",
1008 buffer.Tx_CodecGain.Component_3, buffer.Tx_CodecGain.RegAddr_3, buffer.Tx_CodecGain.RegVal_3);
1009
1010 LOGI(APHAudioPathVolumeSet,"Tx_CodecGain:: Component_4=0x%x, RegAddr_4=0x%x, RegVal_4=0x%x !\n",
1011 buffer.Tx_CodecGain.Component_4, buffer.Tx_CodecGain.RegAddr_4, buffer.Tx_CodecGain.RegVal_4);
1012 //config Tx_CodecGain of acm_nvm.h here.
1013 if (0xFFFF != buffer.Tx_CodecGain.RegAddr_1)
1014 {
1015 Component_NVM = buffer.Tx_CodecGain.Component_1;
1016 Address_NVM = buffer.Tx_CodecGain.RegAddr_1;
1017 Value_NVM = buffer.Tx_CodecGain.RegVal_1;
1018
1019 configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
1020 }
1021
1022 if (0xFFFF != buffer.Tx_CodecGain.RegAddr_2)
1023 {
1024 Component_NVM = buffer.Tx_CodecGain.Component_2;
1025 Address_NVM = buffer.Tx_CodecGain.RegAddr_2;
1026 Value_NVM = buffer.Tx_CodecGain.RegVal_2;
1027
1028 configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
1029 }
1030
1031 if (0xFFFF != buffer.Tx_CodecGain.RegAddr_3)
1032 {
1033 Component_NVM = buffer.Tx_CodecGain.Component_3;
1034 Address_NVM = buffer.Tx_CodecGain.RegAddr_3;
1035 Value_NVM = buffer.Tx_CodecGain.RegVal_3;
1036
1037 configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
1038 }
1039
1040 if (0xFFFF != buffer.Tx_CodecGain.RegAddr_4)
1041 {
1042 Component_NVM = buffer.Tx_CodecGain.Component_4;
1043 Address_NVM = buffer.Tx_CodecGain.RegAddr_4;
1044 Value_NVM = buffer.Tx_CodecGain.RegVal_4;
1045
1046 configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
1047 }
1048 return ACM_RC_OK;
1049#else
1050 return ACM_RC_OK;
1051#endif
1052}
1053
1054
1055ACM_ReturnCode ACM_GetPathStatus(char *buff, unsigned int maxsize) {
1056 unsigned int index = 0, size = 0, total = 0;
1057 char *ptr = buff;
1058
1059 for(index = 0; index < APH_PATH_ID_CNT; index++){
1060 //Prevent buff overwritten: reserve 100 bytes for this time
1061 if(total > maxsize - 100)
1062 return ACM_RC_INVALID_PARAMETER;
1063
1064 size = sprintf(ptr, " : %-30s:%9s,%8s, volume=%d\n", AUDIO_PATH_ID_MAPPING[index].PathName, path_status_table[index].enabled?"enabled":"disabled", path_status_table[index].mute?"muted":"unmuted", path_status_table[index].value);
1065 if(size > 0)
1066 ptr += size;
1067 else
1068 return ACM_RC_INVALID_PARAMETER;
1069 total += size;
1070 }
1071
1072 return ACM_RC_OK;
1073}
1074
1075unsigned int ACM_GetEnabledPathVolume(void)
1076{
1077 int i;
1078 unsigned int enabled_path_id_Rx = INVALID_PATH_ID;
1079 unsigned int enabled_path_id_Tx = INVALID_PATH_ID;
1080 unsigned int enabled_volume_Rx = 80;//refer to the value: madev->voice_volume = 0.8f;
1081 unsigned int enabled_mute_Tx = 0;
1082
1083 for (i=0; i<APH_PATH_ID_CNT; i++)
1084 {
1085 //save the enabled path.
1086 if ( path_status_table[i].enabled)
1087 {
1088 if ((i != APH_PATH_ID_HIFIRECORDFROMMIC1) && (i != APH_PATH_ID_HIFIRECORDFROMHSMIC)
1089 && (i !=APH_PATH_ID_VOICERECORDFROMMIC1) && (i !=APH_PATH_ID_VOICERECORDFROMHSMIC))
1090 {
1091 enabled_path_id_Rx = i;//record Rx path.
1092 enabled_volume_Rx = path_status_table[i].value;
1093 }
1094 else
1095 {
1096 enabled_path_id_Tx = i;//record Tx path.
1097 enabled_mute_Tx = path_status_table[i].mute;
1098 }
1099 }
1100 }
1101
1102 LOGI(ACM_GetEnabledPathVolume, "%s/L%d: enabled_path_id_Rx=%d, enabled_path_id_Tx=%d, enabled_volume_Rx=%d, enabled_mute_Tx=%d,",
1103 __FUNCTION__, __LINE__,enabled_path_id_Rx,enabled_path_id_Tx, enabled_volume_Rx, enabled_mute_Tx);
1104
1105 return enabled_volume_Rx;
1106}
1107
1108ACM_ReturnCode ACM_GetPathDirection(const char *path, unsigned char *path_direction) {
1109 return _get_path_direction(path, path_direction);
1110}
1111
1112ACM_ReturnCode APHGetMSAGain(const char *out_path, const char *path, unsigned char *volume, unsigned short id, signed short *gain, signed short *sidetone_gain) {
1113
1114#if defined(CODEC_PM805) || defined(CODEC_PM812) || defined(CODEC_NAU8810) || defined(CODEC_ALC5616)
1115 int path_id = INVALID_PATH_ID;
1116 AC_IPC_Package package;
1117 ACMCodec_GainT buffer;
1118 unsigned char Volume_value;
1119 unsigned char index_volume;
1120 AUDIO_PROFILE_ID cur_Profile_id = HIFI_HANDSET;
1121
1122 memset(&package, 0x00, sizeof(AC_IPC_Package));
1123 memset(&buffer, 0x00, sizeof(ACMCodec_GainT));
1124
1125 LOGI(APHGetMSAGain, "%s/L%d: out_path=%s, path=%s, volume=%d, id=%d", __FUNCTION__, __LINE__, out_path, path, *volume, id);
1126
1127 //If not equal between out_path and path, it is input device, we need to use out_path to get gain from NVM.
1128 path_id = _get_path_id(out_path);
1129 if(path_id == INVALID_PATH_ID)
1130 {
1131 LOGE(APHGetMSAGain, "%s: ERROR: can not find matched path id", __FUNCTION__);
1132 return ACM_RC_INVALID_PATH;
1133 }
1134
1135 //RX path is mapping to PROFILE.
1136 switch (path_id)
1137 {
1138 case APH_PATH_ID_HIFIPLAYTOEARPHONE:
1139 cur_Profile_id = HIFI_HANDSET;
1140 break;
1141
1142 case APH_PATH_ID_HIFIPLAYTOSPKR:
1143 cur_Profile_id = HIFI_SPEAKER;
1144 break;
1145
1146 case APH_PATH_ID_HIFIPLAYTOHP:
1147 cur_Profile_id = HIFI_HEADSET;
1148 break;
1149
1150 case APH_PATH_ID_VOICEPLAYTOEARPHONE:
1151 cur_Profile_id = VC_HANDSET;
1152 break;
1153
1154 case APH_PATH_ID_VOICEPLAYTOSPKR:
1155 cur_Profile_id = VC_HANDSFREE;
1156 break;
1157
1158 case APH_PATH_ID_VOICEPLAYTOHP:
1159 cur_Profile_id = VC_HEADSET;
1160 break;
1161
1162 default:
1163 LOGI(APHGetMSAGain, "%s/L%d: PATH ID=%d, PATH is %s.", __FUNCTION__, __LINE__, path_id, path);
1164 break;
1165 }
1166
1167 package.type = AUDIO_NVM_GetGainConfigure;
1168 package.body.d1 = 0;
1169 package.body.d2 = cur_Profile_id; //path ID (unsigned short)
1170 package.ptr = &buffer;
1171
1172 NVM_Calibration_IPC(&package);
1173
1174 Volume_value = (unsigned char)((*volume) & VOLUME_MASK);
1175 Volume_value = (Volume_value + 5) /10;
1176 index_volume = Volume_value;
1177 Volume_value *= 10;
1178
1179 if (strcmp(out_path, path))
1180 {//MIC, HSMIC...
1181 *gain = buffer.Tx_DSPGain;
1182 *sidetone_gain = 0;
1183 LOGI(APHGetMSAGain,"APHGetMSAGain::profile=%d, Tx DSP gain = 0x%hx, sidetone = 0x%hx!", buffer.Profile_id, *gain, *sidetone_gain);
1184 }
1185 else
1186 {//EARPHONE, SPEAKER...
1187 *gain = buffer.Rx_DSPGain[index_volume];
1188 *sidetone_gain = buffer.Rx_DSPSideToneGain;
1189 LOGI(APHGetMSAGain,"APHGetMSAGain::profile=%d, Rx DSP gain = 0x%hx, sidetone = 0x%hx!", buffer.Profile_id, *gain, *sidetone_gain);
1190 }
1191
1192 return ACM_RC_OK;
1193
1194#else
1195
1196 *gain = 0;
1197 *sidetone_gain = 0x8080;//0x8080=disable sidetone
1198 LOGI(APHGetMSAGain,"Not supported codec! APHGetMSAGain:: DSP gain = 0x%hx, sidetone = 0x%hx!", *gain, *sidetone_gain);
1199 return ACM_RC_OK;
1200
1201#endif
1202
1203}
1204
1205#ifdef PXA1826_AUDIO
1206ACM_ReturnCode APHSetMSAGain(AC_Digital_Gain *gain) {
1207 VolumeCtlMsg volume_cmd;
1208 int ioctl_fd;
1209
1210 // If no voice path actived, will not configure DSP
1211 if((gain->path_direction_Rx > 1) || (gain->path_direction_Tx > 1))
1212 {
1213 LOGI(APHSetMSAGain, "no voice path actived, will not configure DSP: Rx=%d,Tx=%d", gain->path_direction_Rx, gain->path_direction_Tx);
1214 return ACM_RC_OK;
1215 }
1216
1217 ioctl_fd = open("/dev/audiostub_ctl", O_RDONLY);
1218 if(ioctl_fd < 0)
1219 {
1220 LOGI(APHSetMSAGain, "failed to open audiostub_ctl: %s", strerror(errno));
1221 return ACM_RC_PATH_NOT_ENABLED;
1222 }
1223
1224 //Rx
1225 memset(&volume_cmd, 0, sizeof(volume_cmd));
1226 volume_cmd.direction = gain->path_direction_Rx;
1227 volume_cmd.gain = gain->digital_gain_Rx;
1228 volume_cmd.misc_volume = gain->volume_Rx;
1229 if(ioctl(ioctl_fd, AUDIOSTUB_VOLUMECTL, &volume_cmd) < 0)
1230 {
1231 LOGI(APHSetMSAGain, "audio_stub ioctl error: %s", strerror(errno));
1232 close(ioctl_fd);
1233 return ACM_RC_INVALID_PARAMETER;
1234 }
1235
1236 //Tx
1237 memset(&volume_cmd, 0, sizeof(volume_cmd));
1238 volume_cmd.direction = gain->path_direction_Tx;
1239 volume_cmd.gain = gain->digital_gain_Tx;
1240 volume_cmd.misc_volume = gain->volume_Tx;
1241 if(ioctl(ioctl_fd, AUDIOSTUB_VOLUMECTL, &volume_cmd) < 0)
1242 {
1243 LOGI(APHSetMSAGain, "audio_stub ioctl error: %s", strerror(errno));
1244 close(ioctl_fd);
1245 return ACM_RC_INVALID_PARAMETER;
1246 }
1247
1248 //SideTone
1249 memset(&volume_cmd, 0, sizeof(volume_cmd));
1250 volume_cmd.direction = gain->path_direction_SideTone;
1251 volume_cmd.gain = gain->digital_gain_SideTone;
1252 volume_cmd.misc_volume = gain->volume_SideTone;
1253 if(ioctl(ioctl_fd, AUDIOSTUB_VOLUMECTL, &volume_cmd) < 0)
1254 {
1255 LOGI(APHSetMSAGain, "audio_stub ioctl error: %s", strerror(errno));
1256 close(ioctl_fd);
1257 return ACM_RC_INVALID_PARAMETER;
1258 }
1259
1260 close(ioctl_fd);
1261 LOGI(APHSetMSAGain, "APHSetMSAGain success!");
1262
1263 return ACM_RC_OK;
1264}
1265#endif
1266
1267#ifdef TARGET_mmp_asr1901_KSTR901
1268extern int audio_dsp_send_ve(void* ve);
1269
1270void ACM_SendVEtoADSP(void) {
1271 AC_IPC_Package package;
1272 EnhanceParmsT buffer;
1273
1274 memset(&package, 0x00, sizeof(AC_IPC_Package));
1275 memset(&buffer, 0x00, sizeof(EnhanceParmsT));
1276
1277 LOGI(ACM_SendVEtoADSP, "%s/%d\n", __FUNCTION__, __LINE__);
1278
1279 package.type = AUDIO_NVM_GetVEConfigure;
1280 package.body.d1 = 0;
1281 package.body.d2 = 0;
1282 package.ptr = &buffer;
1283
1284 NVM_Calibration_IPC(&package);
1285 audio_dsp_send_ve(&buffer);
1286}
1287#endif
1288
1289ACM_ReturnCode ACM_GetEnabledPathId(int *path_id_Rx, int *path_id_Tx, int *volume_Rx, int *mute_Tx)
1290{
1291 int i;
1292
1293 int enabled_path_id_Rx = INVALID_PATH_ID;
1294 int enabled_path_id_Tx = INVALID_PATH_ID;
1295 int enabled_volume_Rx = 0;
1296 int enabled_mute_Tx = 0;
1297
1298 for (i=0; i<APH_PATH_ID_CNT; i++)
1299 {
1300 //save the enabled path.
1301 if ( path_status_table[i].enabled)
1302 {
1303 if ((i != APH_PATH_ID_HIFIRECORDFROMMIC1) && (i != APH_PATH_ID_HIFIRECORDFROMHSMIC)
1304 && (i !=APH_PATH_ID_VOICERECORDFROMMIC1) && (i !=APH_PATH_ID_VOICERECORDFROMHSMIC))
1305 {
1306 enabled_path_id_Rx = i;//record Rx path.
1307 enabled_volume_Rx = path_status_table[i].value;
1308 }
1309 else
1310 {
1311 enabled_path_id_Tx = i;//record Tx path.
1312 enabled_mute_Tx = path_status_table[i].mute;
1313 }
1314 }
1315 }
1316
1317 LOGI(ACM_GetEnabledPathId, "%s/L%d: enabled_path_id_Rx=%d, enabled_path_id_Tx=%d, enabled_volume_Rx=%d, enabled_mute_Tx=%d,",
1318 __FUNCTION__, __LINE__,enabled_path_id_Rx,enabled_path_id_Tx, enabled_volume_Rx, enabled_mute_Tx);
1319
1320 *path_id_Rx = enabled_path_id_Rx;
1321 *path_id_Tx = enabled_path_id_Tx;
1322 *volume_Rx = enabled_volume_Rx;
1323 *mute_Tx = enabled_mute_Tx;
1324
1325 return ACM_RC_OK;
1326}
1327
1328ACM_ReturnCode ACM_ReloadCalibrationData(void) {
1329 char tmp_buffer[PATHSTATUS_MAX] = {0};
1330 int i = 0, value;
1331 int path_id_Rx = INVALID_PATH_ID;
1332 int path_id_Tx = INVALID_PATH_ID;
1333 int volume_Rx = 0;
1334 char mute_Tx = 0;
1335 AUDIO_PROFILE_ID cur_Profile_id = HIFI_HANDSET;
1336 AC_IPC_Package package;
1337
1338 /*
1339 First: send message "AUDIO_NVM_ReloadCalibrationData" to NVM server, trigger reload nvm.
1340 No matter whether there is enabled path.
1341 */
1342 memset(&package, 0x00, sizeof(AC_IPC_Package));
1343 package.type = AUDIO_NVM_ReloadCalibrationData;
1344 package.body.d1 = 0;
1345 package.body.d2 = 0;
1346 package.ptr = &value;
1347 NVM_Calibration_IPC(&package);
1348
1349 //Second: get path status.
1350 if (ACM_GetPathStatus(tmp_buffer, PATHSTATUS_MAX) != ACM_RC_OK)
1351 {
1352 LOGE(ACM_ReloadCalibrationData, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
1353 return ACM_RC_PATH_CONFIG_NOT_EXIST;
1354 }
1355
1356 //list the path status, before ReloadCalibrationData
1357 LOGI(ACM_ReloadCalibrationData, "before ReloadCalibrationData, record the path status, current every path status is:\n%s.......", tmp_buffer);
1358
1359 for (i=0; i<APH_PATH_ID_CNT; i++)
1360 {
1361 //save the enabled path.
1362 if ( path_status_table[i].enabled)
1363 {
1364 if ((i != APH_PATH_ID_HIFIRECORDFROMMIC1) && (i != APH_PATH_ID_HIFIRECORDFROMHSMIC)
1365 && (i !=APH_PATH_ID_VOICERECORDFROMMIC1) && (i !=APH_PATH_ID_VOICERECORDFROMHSMIC))
1366 {
1367 path_id_Rx = i;//record Rx path.
1368 volume_Rx = path_status_table[i].value;
1369 }
1370 else
1371 {
1372 path_id_Tx = i;//record Tx path.
1373 mute_Tx = path_status_table[i].mute;
1374 }
1375 }
1376 }
1377
1378 if ((INVALID_PATH_ID == path_id_Rx) || (INVALID_PATH_ID == path_id_Tx))
1379 {
1380 LOGI(ACM_ReloadCalibrationData, "%s/L%d: no enabled path.", __FUNCTION__, __LINE__);
1381 return ACM_RC_OK;
1382 }
1383
1384 LOGI(ACM_ReloadCalibrationData, "%s/L%d: actived path:Rx path:%s, Tx path:%s",
1385 __FUNCTION__, __LINE__, AUDIO_PATH_ID_MAPPING[path_id_Rx].PathName, AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName);
1386
1387 if ((APHAudioPathCheck(AUDIO_PATH_ID_MAPPING[path_id_Rx].PathName, AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName) != ACM_RC_OK_HIFI_MATCHED)
1388 && (APHAudioPathCheck(AUDIO_PATH_ID_MAPPING[path_id_Rx].PathName, AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName) != ACM_RC_OK_VOICE_MATCHED))
1389 {
1390 LOGE(ACM_ReloadCalibrationData, "%s/L%d: Rx path is not matched with Tx path.", __FUNCTION__, __LINE__);
1391 return ACM_RC_PATH_CONFIG_NOT_EXIST;
1392 }
1393
1394 //RX path is mapping to PROFILE.
1395 switch (path_id_Rx)
1396 {
1397 case APH_PATH_ID_HIFIPLAYTOEARPHONE:
1398 cur_Profile_id = HIFI_HANDSET;
1399 break;
1400
1401 case APH_PATH_ID_HIFIPLAYTOSPKR:
1402 cur_Profile_id = HIFI_SPEAKER;
1403 break;
1404
1405 case APH_PATH_ID_HIFIPLAYTOHP:
1406 cur_Profile_id = HIFI_HEADSET;
1407 break;
1408
1409 case APH_PATH_ID_VOICEPLAYTOEARPHONE:
1410 cur_Profile_id = VC_HANDSET;
1411 break;
1412
1413 case APH_PATH_ID_VOICEPLAYTOSPKR:
1414 cur_Profile_id = VC_HANDSFREE;
1415 break;
1416
1417 case APH_PATH_ID_VOICEPLAYTOHP:
1418 cur_Profile_id = VC_HEADSET;
1419 break;
1420
1421 default:
1422 LOGI(ACM_ReloadCalibrationData, "%s/L%d.", __FUNCTION__, __LINE__);
1423 break;
1424 }
1425
1426 LOGI(ACM_ReloadCalibrationData,"AUDIO_NVM_ReloadCalibrationData:: profile=%d, sizeof(AUDIO_PROFILE_ID)=%d!",
1427 cur_Profile_id, sizeof(AUDIO_PROFILE_ID));
1428
1429 //Third:enable the saved path using new config.
1430 APHAudioPathDisable(AUDIO_PATH_ID_MAPPING[path_id_Rx].PathName);
1431 APHAudioPathDisable(AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName);
1432
1433 ACMAudioPathEnable(AUDIO_PATH_ID_MAPPING[path_id_Rx].PathName, volume_Rx);
1434 ACMAudioPathEnable(AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName, volume_Rx);
1435 APHAudioPathMute(AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName, mute_Tx);
1436
1437 //Forth: List the path status.
1438 memset(tmp_buffer, 0x00, sizeof(tmp_buffer));
1439
1440 if (ACM_GetPathStatus(tmp_buffer, PATHSTATUS_MAX) != ACM_RC_OK)
1441 {
1442 LOGE(ACM_ReloadCalibrationData, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
1443 return ACM_RC_PATH_CONFIG_NOT_EXIST;
1444 }
1445
1446 //After recover the enabled path, list the path status
1447 LOGI(ACM_ReloadCalibrationData, "After recover the enabled path, list the path status is:%s.......", tmp_buffer);
1448
1449 return ACM_RC_OK;
1450}
1451
1452void ACM_enable_headset_detection_ALC5616(void)
1453{
1454#ifdef TARGET_mmp_asr1901_KSTR901
1455 system("echo 1 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616-headset/enable_headset_detection");
1456#else
1457 system("echo 1 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616-headset/enable_headset_detection");
1458#endif
1459 return;
1460}
1461
1462void ACM_APHInit(void) {
1463#ifdef PXA1826_AUDIO
1464 int ret = 0;
1465 int err, ioctl_fd, status = 0;
1466#endif
1467 int value;
1468 AC_IPC_Package package;
1469
1470 if (0 == get_debug_mode())
1471 {
1472 /* 1:on; 0:off, default. if g_audio_if_debug_mode is on, no need to send msg to NVMProxy. */
1473
1474 //Reload AP Audio NVM
1475 package.type = AUDIO_NVM_ReloadCalibrationData;
1476 package.body.d1 = 0;
1477 package.body.d2 = 0;
1478 package.ptr = &value;
1479 NVM_Calibration_IPC(&package);
1480 }
1481
1482 //reset components status
1483 if(acm_codec_connected == TRUE){
1484 _reset_components_status();
1485 _reset_components_registers();
1486 }
1487
1488 /*
1489 * From audio_stub, get the properties of nb/wb, master/slave
1490 */
1491#ifdef PXA1826_AUDIO
1492 ioctl_fd = open("/dev/audiostub_ctl", O_RDONLY);
1493 if (ioctl_fd < 0) {
1494 err = errno;
1495 ALOGE(ACM_APHInit9, "failed to open audiostub_ctl:%s\n", strerror(err));
1496 return;
1497 }
1498
1499 ret = ioctl(ioctl_fd, AUDIOSTUB_GET_STATUS, &status);
1500 if (ret < 0) {
1501 ALOGE(ACM_APHInit10, "Warning, audio_stub ioctl error: %s", strerror(errno));
1502 }
1503 modem_is_wb = IS_WB(status);
1504 modem_is_master = IS_PCM_MASTER(status);
1505
1506 LOGI(ACM_APHInit, "%s/L%d: modem_is_wb=%d, modem_is_master=%d", __FUNCTION__, __LINE__, modem_is_wb, modem_is_master);
1507
1508 //close the file after got status report
1509 close(ioctl_fd);
1510#endif
1511}
1512
1513void ACM_APHDeInit(void) {
1514}
1515
1516
1517/* Audio uses PROPERTY_AUDIO_CODEC which is not created by PXA1826 init
1518 * Call from ACMInit() to set property with default value "1"
1519 * depending upon the AUDIO package is better than in init.rc
1520 * (No other setprop are present for now)
1521 */
1522void ACM_Init_Property(void)
1523{
1524 char property_value[PROPERTY_VALUE_MAX];
1525 int i = property_get(PROPERTY_AUDIO_CODEC, property_value, NULL);
1526 if (i <= 0) {
1527 LOGD(ACM_Init_Property, "Not found %s. Create with default value=%d", PROPERTY_AUDIO_CODEC, (modem_is_master == 0)?1:0);
1528 if(modem_is_master == 0)
1529 property_set(PROPERTY_AUDIO_CODEC, "1"); //persist.audio.codecmaster = 1
1530 else
1531 property_set(PROPERTY_AUDIO_CODEC, "0"); //persist.audio.codecmaster = 0
1532 }
1533 else
1534 LOGD(ACM_Init_Property, "Found %s. value=%s", PROPERTY_AUDIO_CODEC, property_value);
1535}
1536