ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/services/audio/libacm/acm/src/acm_aph.c b/marvell/services/audio/libacm/acm/src/acm_aph.c
new file mode 100644
index 0000000..a947a74
--- /dev/null
+++ b/marvell/services/audio/libacm/acm/src/acm_aph.c
@@ -0,0 +1,1536 @@
+/*
+* All Rights Reserved
+*
+* MARVELL CONFIDENTIAL
+* Copyright 2012 Marvell International Ltd All Rights Reserved.
+* The source code contained or described herein and all documents related to
+* the source code ("Material") are owned by Marvell International Ltd or its
+* suppliers or licensors. Title to the Material remains with Marvell International Ltd
+* or its suppliers and licensors. The Material contains trade secrets and
+* proprietary and confidential information of Marvell or its suppliers and
+* licensors. The Material is protected by worldwide copyright and trade secret
+* laws and treaty provisions. No part of the Material may be used, copied,
+* reproduced, modified, published, uploaded, posted, transmitted, distributed,
+* or disclosed in any way without Marvell's prior express written permission.
+*
+* No license under any patent, copyright, trade secret or other intellectual
+* property right is granted to or conferred upon you by disclosure or delivery
+* of the Materials, either expressly, by implication, inducement, estoppel or
+* otherwise. Any license under such intellectual property rights must be
+* express and approved by Marvell in writing.
+*
+*/
+
+#define LOG_TAG "acm_aph"
+#define LOG_NDEBUG 0
+
+#include <stdio.h>
+#include <unistd.h> //usleep
+#include <cutils/properties.h>
+#include <stdlib.h>
+#include <cutils/log.h>
+#include "acm_aph.h"
+#include "acm_param.h"
+#include <stdlib.h>
+
+#ifdef PXA1826_AUDIO
+#include "audio_stub.h"
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#endif
+
+#ifdef TARGET_mmp_asr1901_KSTR901
+#include "audio_dsp.h"
+#include "adsp_ve.h"
+#endif
+
+#include "audioCalibration.h"
+
+//-----------------------------------------------------------------------------
+//Codec Definitions:
+// CODEC_PM812/CODEC_PM805/CODEC_NAU8810/CODEC_ALC5616/CODEC_NONE is defined in openwrt\package\libs\pxa1826_audio
+// CODEC_I2S_MASTER/CODEC_I2S_SLAVE/CODEC_PCM_MASTER/CODEC_PCM_SLAVE is defined in openwrt\package\libs\pxa1826_audio
+//-----------------------------------------------------------------------------
+#if defined(CODEC_PM812)
+//PM812 is connected
+#include "acm_pm812.h"
+static BOOL acm_codec_connected = TRUE;
+#elif defined(CODEC_PM805)
+//PM805 is connected
+#include "acm_pm805.h"
+static BOOL acm_codec_connected = TRUE;
+#elif defined(CODEC_NAU8810)
+//NAU8810 is connected
+#include "acm_nau8810.h"
+static BOOL acm_codec_connected = TRUE;
+#elif defined(CODEC_ALC5616)
+//ALC5616 is connected
+#include "acm_alc5616.h"
+static BOOL acm_codec_connected = TRUE;
+#else
+//No codec is connected
+static BOOL acm_codec_connected = FALSE;
+static ACMAPH_Component ACM_Enable[APH_PATH_ID_CNT]={};
+static ACMAPH_Component ACM_Disable[APH_PATH_ID_CNT]={};
+static ACMAPH_Component ACM_Mute[APH_PATH_IN_CNT]={};
+static ACMAPH_Component ACM_UnMute[APH_PATH_IN_CNT]={};
+static ACMAPH_VolumeComponent ACM_Volume[APH_PATH_OUT_CNT]={};
+static APH_ACHComponent ACH_component_table[AUDIO_COMPONENT_CNT]={};
+//Sorted as APH_AudioComponent
+static char APH_AudioComponent_Name[AUDIO_COMPONENT_CNT][16]= {} ;
+#endif
+
+
+//--------------------------------------------------------------
+//-------- Global Information Tables
+//--------------------------------------------------------------
+
+static int modem_is_wb = 0, modem_is_master = 0;
+
+const ACMAPH_AudioPathID AUDIO_PATH_ID_MAPPING[APH_PATH_ID_CNT] = {
+ {APH_PATH_ID_HIFIPLAYTOEARPHONE, "HiFiPlayToEarphone" },
+ {APH_PATH_ID_HIFIPLAYTOSPKR, "HiFiPlayToSPKR" },
+ {APH_PATH_ID_HIFIPLAYTOHP, "HiFiPlayToHP" },
+ {APH_PATH_ID_HIFIRECORDFROMMIC1, "HiFiRecordFromMic1" },
+ {APH_PATH_ID_HIFIRECORDFROMHSMIC, "HiFiRecordFromHsMic" },
+ {APH_PATH_ID_VOICEPLAYTOEARPHONE, "VoicePlayToEarphone" },
+ {APH_PATH_ID_VOICEPLAYTOSPKR, "VoicePlayToSPKR" },
+ {APH_PATH_ID_VOICEPLAYTOHP, "VoicePlayToHP" },
+ {APH_PATH_ID_VOICERECORDFROMMIC1, "VoiceRecordFromMic1" },
+ {APH_PATH_ID_VOICERECORDFROMHSMIC, "VoiceRecordFromHsMic"},
+};
+
+APH_PathStatus path_status_table[APH_PATH_ID_CNT] = {
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}
+};
+
+/* 1:on; 0:off */
+static int g_audio_if_debug_mode = 0;
+
+int get_debug_mode(void)
+{
+ return g_audio_if_debug_mode;
+}
+
+void set_debug_mode(int onoff)
+{
+ g_audio_if_debug_mode = onoff;
+}
+
+void configCodecGainfromNVM(APH_AudioComponent Component_NVM, unsigned char Address_NVM, unsigned short Value_NVM);
+extern int NVM_Calibration_IPC(AC_IPC_Package *package);
+
+const ACMAPH_AudioPathID *ACM_GetPathConfigTable() {
+ return AUDIO_PATH_ID_MAPPING ;
+}
+
+void get_pcm_config(int *p_role, int *p_rate)
+{
+ *p_role = modem_is_master;
+ *p_rate = modem_is_wb;
+ return;
+}
+
+void set_pcm_config(int role, int rate)
+{
+ modem_is_master = role;
+ modem_is_wb = rate;
+
+#if defined(CODEC_ALC5616)
+#ifdef TARGET_mmp_asr1901_KSTR901
+ if (3 == modem_is_wb) {
+ LOGI(set_pcm_config, "%s: modem switch to 48KHz for ALC5616 in Kestrel.", __FUNCTION__);
+ system("echo 3 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616_switch_rate");
+ } else if (2 == modem_is_wb){
+ LOGI(set_pcm_config, "%s: modem switch to 32KHz for ALC5616 in Kestrel.", __FUNCTION__);
+ system("echo 2 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616_switch_rate");
+ } else if (1 == modem_is_wb) {
+ LOGI(set_pcm_config, "%s: modem switch to WB for ALC5616 in Kestrel.", __FUNCTION__);
+ system("echo 1 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616_switch_rate");
+ } else if (0 == modem_is_wb) {
+ LOGI(set_pcm_config, "%s: modem switch to NB for ALC5616 in Kestrel.", __FUNCTION__);
+ system("echo 0 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616_switch_rate");
+ } else {
+ LOGI(set_pcm_config, "%s: modem switch to NB for ALC5616 in Kestrel.", __FUNCTION__);
+ system("echo 0 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616_switch_rate");
+ }
+#else
+ if (1 == modem_is_wb) {
+ LOGI(set_pcm_config, "%s: modem switch to WB for ALC5616.", __FUNCTION__);
+ system("echo 1 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616_switch_rate");
+ } else {
+ LOGI(set_pcm_config, "%s: modem switch to NB for ALC5616.", __FUNCTION__);
+ system("echo 0 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616_switch_rate");
+ }
+#endif
+#endif
+
+ LOGI(set_pcm_config, "%s: modem_is_master=%s, modem_is_wb=%s.", __FUNCTION__, modem_is_master?"TRUE":"FALSE", modem_is_wb?"WB":"NB");
+ return;
+}
+
+static int _get_path_id(const char *path) {
+ const ACMAPH_AudioPathID *ptr;
+ const char *PathName;
+ unsigned int i = 0, size;
+
+ if(path == NULL)
+ return INVALID_PATH_ID;
+
+ size = sizeof(AUDIO_PATH_ID_MAPPING)/sizeof(ACMAPH_AudioPathID);
+ ptr = &AUDIO_PATH_ID_MAPPING[0];
+ while (i < size) {
+ PathName = ptr->PathName;
+ if (strcmp((const char *)path, (const char *)PathName) == 0) {
+ LOGI(_get_path_id, "%s: path=%s, PathName=%s,PathID=%d, i=%d", __FUNCTION__, path, PathName,ptr->PathID, i);
+ return ptr->PathID;
+ }
+
+ ptr++;
+ i++;
+ }
+
+ return INVALID_PATH_ID;
+}
+
+static ACMAPH_Component *_get_APHTable(APH_PATH_ID path_id, ACMAPH_Component *pTable, unsigned char max) {
+ int i = 0;
+
+ for (i = 0; i < max; i++) {
+ if (pTable[i].PathID == path_id) {
+ LOGI(_get_APHTable, "%s: path_id=%d", __FUNCTION__, path_id);
+ return &pTable[i];
+ }
+ }
+
+ return NULL;
+}
+
+#if !defined(CODEC_PM805) && !defined(CODEC_PM812) && !defined(CODEC_NAU8810) && !defined(CODEC_ALC5616)
+static ACMAPH_VolumeComponent *_get_APHVolumeTable(APH_PATH_ID path_id, ACMAPH_VolumeComponent *pTable, unsigned char max) {
+ int i = 0;
+
+ for (i = 0; i < max; i++) {
+ if (pTable[i].PathID == path_id) {
+ LOGI(_get_APHVolumeTable, "%s: path_id=%d", __FUNCTION__, path_id);
+ return &pTable[i];
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+static ACH_ComponentHandler *_get_component_handler(APH_AudioComponent component_id) {
+ int size = sizeof(ACH_component_table) / sizeof(ACH_component_table[0]);
+ int i = 0;
+
+ for (i = 0; i < size; i++) {
+ if (ACH_component_table[i].component_id == component_id) {
+ LOGI(_get_component_handler, "%s: component_id=%d", __FUNCTION__, component_id);
+ return ACH_component_table[i].component_handler;
+ }
+ }
+
+ return NULL;
+}
+
+static void _reset_components_registers() {
+ int size = sizeof(ACH_component_table) / sizeof(ACH_component_table[0]);
+ int i = 0;
+
+ /* Disable all components when init.*/
+ for (i = 0; i < size; i++) {
+ if (ACH_component_table[i].component_handler) {
+ ACH_component_table[i].component_handler->ACH_Reset();
+ }
+ }
+}
+
+static void _reset_components_status() {
+ int size = sizeof(ACH_component_table) / sizeof(ACH_component_table[0]);
+ int i = 0;
+
+ for (i = 0; i < size; i++) {
+ ACH_component_table[i].component_handler->active = COMPONENT_INACTIVE;
+ ACH_component_table[i].component_handler->ref_count = 0;
+ }
+
+ /* Disable all components when init.*/
+ for (i = 0; i < size; i++) {
+ ACH_component_table[i].component_handler->ACH_Disable();
+ }
+}
+
+static ACM_ReturnCode _get_path_direction(const char *path, unsigned char *path_direction) {
+ ACM_ReturnCode ret = ACM_RC_INVALID_PARAMETER;
+ if(path != NULL) {
+ if(strstr((const char *)path, "PlayTo") != NULL) {
+ *path_direction = PATH_DIRECTION_OUT;
+ ret = ACM_RC_OK;
+ }
+ if(strstr((const char *)path, "RecordFrom") != NULL) {
+ *path_direction = PATH_DIRECTION_IN;
+ ret = ACM_RC_OK;
+ }
+ }
+ return ret;
+}
+
+char * ACM_GetPathName(int PathID) {
+ const ACMAPH_AudioPathID *ptr;
+ unsigned int i = 0, size;
+
+ if(PathID >= APH_PATH_ID_CNT) {
+ return NULL;
+ }
+
+ size = sizeof(AUDIO_PATH_ID_MAPPING)/sizeof(ACMAPH_AudioPathID);
+ ptr = &AUDIO_PATH_ID_MAPPING[0];
+ while (i < size) {
+ if (PathID == ptr->PathID) {
+ LOGI(_get_PathName, "%s: PathName=%s, PathID=%d, i=%d", __FUNCTION__, ptr->PathName,ptr->PathID, i);
+ return ptr->PathName;
+ }
+
+ ptr++;
+ i++;
+ }
+
+ return NULL;
+}
+
+ACM_ReturnCode APHAudioPathEnable(const char * path, unsigned int value) {
+ int path_id = INVALID_PATH_ID;
+ APH_AudioComponent component;
+ ACMAPH_Register *RegisterList;
+ unsigned int i, size;
+ ACH_ComponentParameter param;
+ ACH_ComponentHandler *component_handler = NULL;
+ ACMAPH_Component *pTable = NULL;
+
+ 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);
+
+ if(acm_codec_connected == TRUE){
+ LOGI(APHAudioPathEnable, "%s/L%d: path=%s, value=0x%x", __FUNCTION__, __LINE__, path, value);
+ }
+ else {
+ LOGE(APHAudioPathEnable, "%s/L%d: path=%s, no codec connected!", __FUNCTION__, __LINE__, path);
+ return ACM_RC_INVALID_PARAMETER;
+ }
+
+ path_id = _get_path_id(path);
+ if(path_id == INVALID_PATH_ID){
+ LOGE(APHAudioPathEnable, "%s/L%d: Error path_id=%d", __FUNCTION__, __LINE__, path_id);
+ return ACM_RC_INVALID_PATH;
+ }
+
+ pTable = _get_APHTable(path_id, ACM_Enable, APH_PATH_ID_CNT);
+ if(pTable == NULL){
+ LOGE(APHAudioPathEnable, "%s/L%d: Error pTable=%d", __FUNCTION__, __LINE__, pTable);
+ return ACM_RC_INVALID_PATH;
+ }
+
+ if(path_status_table[path_id].enabled != 0){
+ LOGE(APHAudioPathEnable, "%s/L%d: Already enable path %s(%d)", __FUNCTION__, __LINE__, path, path_id);
+ return ACM_RC_PATH_ALREADY_ENABLED;
+ }
+ else{
+ path_status_table[path_id].enabled = 1;
+ }
+
+ size = pTable->RegisterNum;
+ RegisterList = pTable->RegisterList;
+
+ for(i = 0; i < size; i++){
+ // get matched component
+ component = RegisterList[i].Component;
+ if(component == DELAY){
+ usleep(RegisterList[i].Value * 1000);
+ continue;
+ }
+
+ if(_get_component_handler(component) != component_handler ){
+ component_handler = _get_component_handler(component);
+
+ ///update component_handler-->ref_count: it depends on registers sorting style
+ component_handler->ref_count++;
+ LOGI(APHAudioPathEnable, "%s/L%d: component=%s, ref_count=%d", __FUNCTION__, __LINE__, APH_AudioComponent_Name[component], component_handler->ref_count);
+ }
+
+ //firstly enable component
+ if(component_handler->active == COMPONENT_INACTIVE){
+ component_handler->ACH_Enable();
+ component_handler->active = COMPONENT_ACTIVE;
+ }
+
+ /*
+ * Set value according to modem_is_wb & modem_is_master
+ *
+ */
+ //The registers of PM812 are identical with PM805
+#if defined(CODEC_PM812)
+ if( RegisterList[i].Address == CODEC_PM812_VOICE_REG35){
+ LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_master?"master":"slave");
+ if (1 == modem_is_master)
+ RegisterList[i].Value = CODEC_PM812_VOICE_SLAVE;
+ else
+ RegisterList[i].Value = CODEC_PM812_VOICE_MASTER;
+ }
+
+ if( RegisterList[i].Address == CODEC_PM812_VOICE_REG36){
+ LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_wb?"16KHz":"8KHz");
+ if (1 == modem_is_wb)
+ RegisterList[i].Value = CODEC_PM812_VOICE_WB;
+ else
+ RegisterList[i].Value = CODEC_PM812_VOICE_NB;
+ }
+#elif defined(CODEC_PM805)
+ if( RegisterList[i].Address == CODEC_PM805_AUDIO_REG30){
+ #if defined(CODEC_I2S_MASTER)
+ RegisterList[i].Value = CODEC_PM805_AUDIO_MASTER;
+ LOGI(APHAudioPathEnable, "%s/L%d: CODEC_PM805_AUDIO_MASTER.", __FUNCTION__, __LINE__);
+ #endif
+
+ #if defined(CODEC_I2S_SLAVE)
+ RegisterList[i].Value = CODEC_PM805_AUDIO_SLAVE;
+ LOGI(APHAudioPathEnable, "%s/L%d: CODEC_PM805_AUDIO_SLAVE.", __FUNCTION__, __LINE__);
+ #endif
+ }
+
+ if( RegisterList[i].Address == CODEC_PM805_VOICE_REG35){
+ LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_master?"master":"slave");
+ if (1 == modem_is_master)
+ RegisterList[i].Value = CODEC_PM805_VOICE_SLAVE;
+ else
+ RegisterList[i].Value = CODEC_PM805_VOICE_MASTER;
+ }
+
+ if( RegisterList[i].Address == CODEC_PM805_VOICE_REG36){
+ LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_wb?"16KHz":"8KHz");
+ if (1 == modem_is_wb)
+ RegisterList[i].Value = CODEC_PM805_VOICE_WB;
+ else
+ RegisterList[i].Value = CODEC_PM805_VOICE_NB;
+ }
+#elif defined(CODEC_NAU8810)
+ if( RegisterList[i].Address == CODEC_NAU8810_VOICE_REG06){
+ LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_master?"master":"slave");
+ if (1 == modem_is_master)
+ RegisterList[i].Value = CODEC_NAU8810_VOICE_SLAVE;
+ else
+ RegisterList[i].Value = CODEC_NAU8810_VOICE_MASTER;
+ }
+
+ if( RegisterList[i].Address == CODEC_NAU8810_VOICE_REG07){
+ LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_wb?"16KHz":"8KHz");
+ if (1 == modem_is_wb)
+ RegisterList[i].Value = CODEC_NAU8810_VOICE_WB;
+ else
+ RegisterList[i].Value = CODEC_NAU8810_VOICE_NB;
+ }
+#elif defined(CODEC_ALC5616)
+ if( RegisterList[i].Address == CODEC_ALC5616_VOICE_REG70){
+ LOGI(APHAudioPathEnable, "%s/L%d: modem PCM is %s", __FUNCTION__, __LINE__, modem_is_master?"master":"slave");
+ if (1 == modem_is_master)
+ RegisterList[i].Value = CODEC_ALC5616_VOICE_SLAVE;
+ else
+ RegisterList[i].Value = CODEC_ALC5616_VOICE_MASTER;
+ }
+
+ //WB/NB is set in kernel file driver/mfd/alc5616.c.
+#endif
+ //fill param
+ param.i2c.reg_index = RegisterList[i].Address;
+ param.i2c.reg_value = &RegisterList[i].Value;
+ param.i2c.reg_mask = 0xffff;
+ param.i2c.reg_shift = 0;
+ param.i2c.length = sizeof(short);
+
+ //configure component
+ component_handler->ACH_Handle(¶m);
+ }
+
+ return ACM_RC_OK;
+}
+
+ACM_ReturnCode APHAudioPathDisable(const char * path) {
+ int path_id = INVALID_PATH_ID;
+ APH_AudioComponent component;
+ ACMAPH_Register *RegisterList;
+ unsigned int i, size;
+ ACH_ComponentParameter param;
+ ACH_ComponentHandler *component_handler = NULL;
+ ACMAPH_Component *pTable = NULL;
+
+ if(acm_codec_connected == TRUE){
+ LOGI(APHAudioPathDisable, "%s/L%d: path=%s", __FUNCTION__, __LINE__, path);
+ }
+ else {
+ LOGE(APHAudioPathDisable, "%s/L%d: path=%s, no codec connected!", __FUNCTION__, __LINE__, path);
+ return ACM_RC_INVALID_PARAMETER;
+ }
+
+ path_id = _get_path_id(path);
+ if(path_id == INVALID_PATH_ID){
+ LOGE(APHAudioPathDisable, "%s/L%d: Error path_id=%d", __FUNCTION__, __LINE__, path_id);
+ return ACM_RC_INVALID_PATH;
+ }
+
+ pTable = _get_APHTable(path_id, ACM_Disable, APH_PATH_ID_CNT);
+ if(pTable == NULL){
+ LOGE(APHAudioPathDisable, "%s/L%d: Error pTable=%d", __FUNCTION__, __LINE__, pTable);
+ return ACM_RC_INVALID_PATH;
+ }
+
+ if(path_status_table[path_id].enabled == 0){
+ LOGE(APHAudioPathDisable, "%s/L%d: Already disable path %s(%d)", __FUNCTION__, __LINE__, path, path_id);
+ return ACM_RC_PATH_ALREADY_DISABLED;
+ }
+ else{
+ path_status_table[path_id].enabled = 0;
+ ////path_status_table[path_id].value = 0; // Save volume even after disabled
+ path_status_table[path_id].mute = 0;
+ }
+
+ size = pTable->RegisterNum;
+ RegisterList = pTable->RegisterList;
+
+ for(i = 0; i < size; i++){
+ // get matched component
+ component = RegisterList[i].Component;
+ if(component == DELAY){
+ usleep(RegisterList[i].Value * 1000);
+ continue;
+ }
+
+ if(_get_component_handler(component) != component_handler ){
+ component_handler = _get_component_handler(component);
+
+ ///update component_handler-->ref_count: it depends on registers sorting style
+ component_handler->ref_count--;
+ LOGI(APHAudioPathDisable, "%s/L%d: component=%s, ref_count=%d", __FUNCTION__, __LINE__, APH_AudioComponent_Name[component], component_handler->ref_count);
+ }
+
+ //fill param
+ param.i2c.reg_index = RegisterList[i].Address;
+ param.i2c.reg_value = &RegisterList[i].Value;
+ param.i2c.reg_mask = 0xffff;
+ param.i2c.reg_shift = 0;
+ param.i2c.length = sizeof(short);
+
+ //configure component
+ component_handler->ACH_Handle(¶m);
+
+ //Last: if this component is not referred anymore,disable component
+ if(component_handler->ref_count == 0){
+ if(component_handler->active == COMPONENT_ACTIVE){
+ component_handler->ACH_Disable();
+ component_handler->active = COMPONENT_INACTIVE;
+ }
+ }
+ }
+
+ return ACM_RC_OK;
+}
+
+ACM_ReturnCode APHAudioPathCheckPathId (int path_id_Rx, int path_id_Tx) {
+
+ if ((path_id_Rx == INVALID_PATH_ID) || (path_id_Tx == INVALID_PATH_ID))
+ {
+ LOGE(APHAudioPathCheckPathId, "%s/L%d: Error", __FUNCTION__, __LINE__);
+ return ACM_RC_INVALID_PATH;
+ }
+
+ if (((APH_PATH_ID_HIFIPLAYTOEARPHONE == path_id_Rx) ||(APH_PATH_ID_HIFIPLAYTOSPKR == path_id_Rx))
+ && (APH_PATH_ID_HIFIRECORDFROMMIC1 == path_id_Tx))
+ {
+ return ACM_RC_OK_HIFI_MATCHED;
+ }
+ else if ((APH_PATH_ID_HIFIPLAYTOHP == path_id_Rx) && (APH_PATH_ID_HIFIRECORDFROMHSMIC == path_id_Tx))
+ {
+ return ACM_RC_OK_HIFI_MATCHED;
+ }
+ else if (((APH_PATH_ID_VOICEPLAYTOEARPHONE == path_id_Rx) ||(APH_PATH_ID_VOICEPLAYTOSPKR == path_id_Rx)
+ || (APH_PATH_ID_VOICEPLAYTOHP == path_id_Rx))
+ && (APH_PATH_ID_VOICERECORDFROMMIC1 == path_id_Tx))
+ {
+ return ACM_RC_OK_VOICE_MATCHED;
+ }
+ else if ((APH_PATH_ID_VOICEPLAYTOHP == path_id_Rx) && (APH_PATH_ID_VOICERECORDFROMHSMIC == path_id_Tx))
+ {
+ return ACM_RC_OK_VOICE_MATCHED;
+ }
+ else
+ {
+ return ACM_RC_PATH_CONFIG_NOT_EXIST;
+ }
+
+ return ACM_RC_OK;
+}
+
+ACM_ReturnCode APHAudioPathCheck (const char * path_Rx, const char * path_Tx) {
+
+ int path_id_Rx = INVALID_PATH_ID;
+ int path_id_Tx = INVALID_PATH_ID;
+
+ if ((NULL == path_Rx) || (NULL == path_Tx))
+ {
+ LOGE(APHAudioPathCheck, "%s/L%d: Rx path or Tx path is NULL, please check it.", __FUNCTION__, __LINE__);
+ return ACM_RC_PATH_CONFIG_NOT_EXIST;
+ }
+
+ path_id_Rx = _get_path_id(path_Rx);
+ path_id_Tx = _get_path_id(path_Tx);
+
+ if((path_id_Rx == INVALID_PATH_ID) || (path_id_Tx == INVALID_PATH_ID) )
+ {
+ LOGE(APHAudioPathCheck, "%s/L%d: Error", __FUNCTION__, __LINE__);
+ return ACM_RC_INVALID_PATH;
+ }
+
+ if (((APH_PATH_ID_HIFIPLAYTOEARPHONE == path_id_Rx) ||(APH_PATH_ID_HIFIPLAYTOSPKR == path_id_Rx))
+ && (APH_PATH_ID_HIFIRECORDFROMMIC1 == path_id_Tx))
+ {
+ return ACM_RC_OK_HIFI_MATCHED;
+ }
+ else if ((APH_PATH_ID_HIFIPLAYTOHP == path_id_Rx) && (APH_PATH_ID_HIFIRECORDFROMHSMIC == path_id_Tx))
+ {
+ return ACM_RC_OK_HIFI_MATCHED;
+ }
+ else if (((APH_PATH_ID_VOICEPLAYTOEARPHONE == path_id_Rx) ||(APH_PATH_ID_VOICEPLAYTOSPKR == path_id_Rx)
+ || (APH_PATH_ID_VOICEPLAYTOHP == path_id_Rx))
+ && (APH_PATH_ID_VOICERECORDFROMMIC1 == path_id_Tx))
+ {
+ return ACM_RC_OK_VOICE_MATCHED;
+ }
+ else if ((APH_PATH_ID_VOICEPLAYTOHP == path_id_Rx) && (APH_PATH_ID_VOICERECORDFROMHSMIC == path_id_Tx))
+ {
+ return ACM_RC_OK_VOICE_MATCHED;
+ }
+ else
+ {
+ return ACM_RC_PATH_CONFIG_NOT_EXIST;
+ }
+
+ return ACM_RC_OK;
+}
+
+void APHDisableAllPath(void)
+{
+ int i = 0;
+
+ //disable the enabled path
+ for (i=0; i<APH_PATH_ID_CNT; i++)
+ {
+ //disable the enabled path
+ if ( path_status_table[i].enabled)
+ {
+ LOGI(APHDisableAllPath, "disable the path:%s.......", AUDIO_PATH_ID_MAPPING[i].PathName);
+ ACMAudioPathDisable(AUDIO_PATH_ID_MAPPING[i].PathName);
+ }
+ }
+
+ return;
+}
+
+ACM_ReturnCode APHAudioPathSwitch (const char * path_Rx, const char * path_Tx, unsigned int value) {
+
+ char tmp_buffer[PATHSTATUS_MAX] = {0};
+ int i = 0;
+
+ if ((APHAudioPathCheck(path_Rx, path_Tx) != ACM_RC_OK_HIFI_MATCHED)
+ && (APHAudioPathCheck(path_Rx, path_Tx) != ACM_RC_OK_VOICE_MATCHED))
+ {
+ LOGE(APHAudioPathSwitch, "%s/L%d: Rx path is not matched with Tx path.", __FUNCTION__, __LINE__);
+ return ACM_RC_PATH_CONFIG_NOT_EXIST;
+ }
+
+ if (ACM_GetPathStatus(tmp_buffer, PATHSTATUS_MAX) != ACM_RC_OK)
+ {
+ LOGE(APHAudioPathSwitch, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
+ return ACM_RC_PATH_CONFIG_NOT_EXIST;
+ }
+
+ //before switch, before disable, list the path status
+ LOGI(APHAudioPathSwitch, "before switch, before disable, current every path status is:%s.......", tmp_buffer);
+
+ //disable the enabled path
+ for (i=0; i<APH_PATH_ID_CNT; i++)
+ {
+ //disable the enabled path
+ if ( path_status_table[i].enabled)
+ {
+ LOGI(APHAudioPathSwitch, "disable the path:%s.......", AUDIO_PATH_ID_MAPPING[i].PathName);
+ ACMAudioPathDisable(AUDIO_PATH_ID_MAPPING[i].PathName);
+ }
+ }
+
+ memset(tmp_buffer, 0x00, sizeof(tmp_buffer));
+
+ if (ACM_GetPathStatus(tmp_buffer, PATHSTATUS_MAX) != ACM_RC_OK)
+ {
+ LOGE(APHAudioPathSwitch, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
+ return ACM_RC_PATH_CONFIG_NOT_EXIST;
+ }
+
+ //before switch, after disable, list the path status
+ LOGI(APHAudioPathSwitch, "before switch, after disable, current every path status is:%s.......", tmp_buffer);
+
+ //enable the Rx path, and Tx path
+ ACMAudioPathEnable(path_Rx, value);
+ ACMAudioPathEnable(path_Tx, value);
+
+ memset(tmp_buffer, 0x00, sizeof(tmp_buffer));
+
+ if (ACM_GetPathStatus(tmp_buffer, PATHSTATUS_MAX) != ACM_RC_OK)
+ {
+ LOGE(APHAudioPathSwitch, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
+ return ACM_RC_PATH_CONFIG_NOT_EXIST;
+ }
+
+ //before switch, after disable, list the path status
+ LOGI(APHAudioPathSwitch, "after switch, after disable, current every path status is:%s.......", tmp_buffer);
+
+ return ACM_RC_OK;
+}
+
+ACM_ReturnCode APHAudioPathMute(const char * path, unsigned int value) {
+ int path_id = INVALID_PATH_ID;
+ APH_AudioComponent component;
+ ACMAPH_Register *RegisterList;
+ unsigned int i, size;
+ ACH_ComponentParameter param;
+ ACH_ComponentHandler *component_handler = NULL;
+ ACMAPH_Component *pTable = NULL;
+
+ if(acm_codec_connected == TRUE){
+ LOGI(APHAudioPathMute, "%s/L%d: path=%s, %s", __FUNCTION__, __LINE__, path, value?"Mute":"UnMute");
+ }
+ else {
+ LOGE(APHAudioPathMute, "%s/L%d: path=%s, no codec connected!", __FUNCTION__, __LINE__, path);
+ return ACM_RC_INVALID_PARAMETER;
+ }
+
+ path_id = _get_path_id(path);
+ if(path_id == INVALID_PATH_ID){
+ LOGE(APHAudioPathMute, "%s/L%d: Error path_id=%d", __FUNCTION__, __LINE__, path_id);
+ return ACM_RC_INVALID_PATH;
+ }
+
+ if(value == 0)
+ pTable = _get_APHTable(path_id, ACM_UnMute, APH_PATH_IN_CNT);
+ else
+ pTable = _get_APHTable(path_id, ACM_Mute, APH_PATH_IN_CNT);
+ if(pTable == NULL){
+ LOGE(APHAudioPathMute, "%s/L%d: not in pTable{ACM_Mute,ACM_UnMute}=%d, path=%s", __FUNCTION__, __LINE__, pTable, path);
+ return ACM_RC_INVALID_PATH;
+ }
+
+ if(path_status_table[path_id].enabled == 0){
+ LOGE(APHAudioPathMute, "%s/L%d: Count not operate on disabled path %s(%d)", __FUNCTION__, __LINE__, path, path_id);
+ return ACM_RC_PATH_ALREADY_DISABLED;
+ }
+
+ if(path_status_table[path_id].mute == value){
+ LOGE(APHAudioPathMute, "%s/L%d: path %s(%d) is already %", __FUNCTION__, __LINE__, path, path_id, value?"Mute":"UnMute");
+ return ACM_RC_NO_MUTE_CHANGE_NEEDED;
+ }
+ path_status_table[path_id].mute = value;
+
+ size = pTable->RegisterNum;
+ RegisterList = pTable->RegisterList;
+
+ for(i = 0; i < size; i++){
+ // get matched component
+ component = RegisterList[i].Component;
+ if(component == DELAY){
+ usleep(RegisterList[i].Value * 1000);
+ continue;
+ }
+
+ if(_get_component_handler(component) != component_handler ){
+ component_handler = _get_component_handler(component);
+
+ ///update component_handler-->ref_count: it depends on registers sorting style
+ component_handler->ref_count--;
+ LOGI(APHAudioPathMute, "%s/L%d: component=%s, ref_count=%d", __FUNCTION__, __LINE__, APH_AudioComponent_Name[component], component_handler->ref_count);
+ }
+
+ //fill param
+ param.i2c.reg_index = RegisterList[i].Address;
+ param.i2c.reg_value = &RegisterList[i].Value;
+ param.i2c.reg_mask = 0xffff;
+ param.i2c.reg_shift = 0;
+ param.i2c.length = sizeof(short);
+
+ //configure component
+ component_handler->ACH_Handle(¶m);
+ }
+
+ return ACM_RC_OK;
+}
+
+void configCodecGainfromNVM(APH_AudioComponent Component_NVM, unsigned char Address_NVM, unsigned short Value_NVM)
+{
+ ACH_ComponentHandler *component_handler = NULL;
+ APH_AudioComponent component;
+ ACH_ComponentParameter param;
+
+ LOGI(configCodecGainfromNVM,"%s/L%d:: Component=[%d], Address_NVM=[0X%x], Value_NVM=[0X%x] !",
+ __FUNCTION__, __LINE__, Component_NVM, Address_NVM, Value_NVM);
+
+ //if(volume == RegisterList[i].Volume ){
+ // get matched component
+ component = Component_NVM;
+ //component = RegisterList[i].Component;
+ if(component == DELAY)
+ {
+ //usleep(RegisterList[i].Value * 1000);
+ usleep(Value_NVM * 1000);
+ return;
+ }
+
+ if(_get_component_handler(component) != component_handler )
+ {
+ component_handler = _get_component_handler(component);
+
+ ///update component_handler-->ref_count: it depends on registers sorting style
+ component_handler->ref_count--;
+ LOGI(configCodecGainfromNVM, "%s/L%d: component=%s, ref_count=%d", __FUNCTION__, __LINE__, APH_AudioComponent_Name[component], component_handler->ref_count);
+ }
+
+ //fill param
+ param.i2c.reg_index = Address_NVM;
+ param.i2c.reg_value = &Value_NVM;
+ param.i2c.reg_mask = 0xffff;
+ param.i2c.reg_shift = 0;
+ param.i2c.length = sizeof(short);
+
+ LOGI(configCodecGainfromNVM,"%s/L%d:: Address = 0X%x, .Value=0X%x!", __FUNCTION__, __LINE__, Address_NVM, Value_NVM);
+
+ //configure component
+ component_handler->ACH_Handle(¶m);
+
+ return;
+}
+
+ACM_ReturnCode APHAudioPathVolumeSet(const char * path, unsigned int value) {
+ int path_id = INVALID_PATH_ID;
+ unsigned char volume = 0;
+ unsigned int i;
+ unsigned char index_volume = 0;
+
+#if defined(CODEC_PM805) || defined(CODEC_PM812) || defined(CODEC_NAU8810) || defined(CODEC_ALC5616)
+ AC_IPC_Package package;
+ ACMCodec_GainT buffer;
+ AUDIO_PROFILE_ID cur_Profile_id = HIFI_HANDSET;
+
+ APH_AudioComponent Component_NVM;
+ unsigned char Address_NVM;
+ unsigned short Value_NVM;
+
+ memset(&package, 0x00, sizeof(AC_IPC_Package));
+ memset(&buffer, 0x00, sizeof(ACMCodec_GainT));
+#else
+ ACMAPH_VolumeComponent *pTable = NULL;
+#endif
+
+ if(acm_codec_connected == TRUE){
+ LOGI(APHAudioPathVolumeSet, "%s/L%d: path=%s, value=0x%x", __FUNCTION__, __LINE__, path, value);
+ }
+ else {
+ LOGE(APHAudioPathVolumeSet, "%s/L%d: path=%s, no codec connected!", __FUNCTION__, __LINE__, path);
+ return ACM_RC_INVALID_PARAMETER;
+ }
+
+ path_id = _get_path_id(path);
+ if(path_id == INVALID_PATH_ID){
+ LOGE(APHAudioPathVolumeSet, "%s/L%d: Error path_id=%d", __FUNCTION__, __LINE__, path_id);
+ return ACM_RC_INVALID_PATH;
+ }
+
+#if defined(CODEC_PM805) || defined(CODEC_PM812) || defined(CODEC_NAU8810) || defined(CODEC_ALC5616)
+ if ((APH_PATH_ID_HIFIRECORDFROMMIC1 == path_id) || (APH_PATH_ID_HIFIRECORDFROMHSMIC == path_id)
+ || (APH_PATH_ID_VOICERECORDFROMMIC1 == path_id) ||(APH_PATH_ID_VOICERECORDFROMHSMIC == path_id))
+ {
+ LOGI(APHAudioPathVolumeSet, "===%s/L%d: PATH ID=%d, no need to config Tx gain! ===", __FUNCTION__, __LINE__, path_id);
+ return ACM_RC_OK;
+ }
+
+ //RX path is mapping to PROFILE.
+ switch (path_id)
+ {
+ case APH_PATH_ID_HIFIPLAYTOEARPHONE:
+ cur_Profile_id = HIFI_HANDSET;
+ break;
+
+ case APH_PATH_ID_HIFIPLAYTOSPKR:
+ cur_Profile_id = HIFI_SPEAKER;
+ break;
+
+ case APH_PATH_ID_HIFIPLAYTOHP:
+ cur_Profile_id = HIFI_HEADSET;
+ break;
+
+ case APH_PATH_ID_VOICEPLAYTOEARPHONE:
+ cur_Profile_id = VC_HANDSET;
+ break;
+
+ case APH_PATH_ID_VOICEPLAYTOSPKR:
+ cur_Profile_id = VC_HANDSFREE;
+ break;
+
+ case APH_PATH_ID_VOICEPLAYTOHP:
+ cur_Profile_id = VC_HEADSET;
+ break;
+
+ default:
+ LOGI(APHAudioPathVolumeSet, "%s/L%d: PATH ID=%d, PATH is %s.", __FUNCTION__, __LINE__, path_id, path);
+ break;
+ }
+
+ package.type = AUDIO_NVM_GetGainConfigure;
+ package.body.d1 = 0;
+ package.body.d2 = cur_Profile_id; //path ID (unsigned short)
+ package.ptr = &buffer;
+
+ NVM_Calibration_IPC(&package);
+
+ LOGI(APHAudioPathVolumeSet,"APHAudioPathVolumeSet:: profile=%d, Tx_DSPGain=%d, sizeof(AUDIO_PROFILE_ID)=%d!",
+ buffer.Profile_id, buffer.Tx_DSPGain, sizeof(AUDIO_PROFILE_ID));
+
+ for (i=0; i<AUDIOHAL_SPK_VOL_QTY; i++)
+ {
+ LOGI(APHAudioPathVolumeSet,"Rx_CodecGain[%d]:: Component_1=0x%x, RegAddr_1=0x%x, RegVal_1=0x%x !",
+ i, buffer.Rx_CodecGain[i].Component_1, buffer.Rx_CodecGain[i].RegAddr_1, buffer.Rx_CodecGain[i].RegVal_1);
+
+ LOGI(APHAudioPathVolumeSet,"Rx_CodecGain[%d]:: Component_2=0x%x, RegAddr_2=0x%x, RegVal_2=0x%x !",
+ i, buffer.Rx_CodecGain[i].Component_2, buffer.Rx_CodecGain[i].RegAddr_2, buffer.Rx_CodecGain[i].RegVal_2);
+
+ LOGI(APHAudioPathVolumeSet,"Rx_CodecGain[%d]:: Component_3=0x%x, RegAddr_3=0x%x, RegVal_3=0x%x !\n",
+ i, buffer.Rx_CodecGain[i].Component_3, buffer.Rx_CodecGain[i].RegAddr_3, buffer.Rx_CodecGain[i].RegVal_3);
+
+ LOGI(APHAudioPathVolumeSet,"Rx_CodecGain[%d]:: Component_4=0x%x, RegAddr_4=0x%x, RegVal_4=0x%x !\n",
+ i, buffer.Rx_CodecGain[i].Component_4, buffer.Rx_CodecGain[i].RegAddr_4, buffer.Rx_CodecGain[i].RegVal_4);
+ }
+
+#endif
+
+#if !defined(CODEC_PM805) && !defined(CODEC_PM812) && !defined(CODEC_NAU8810) && !defined(CODEC_ALC5616)
+ pTable = _get_APHVolumeTable(path_id, ACM_Volume, APH_PATH_OUT_CNT);
+ if(pTable == NULL){
+ LOGE(APHAudioPathVolumeSet, "%s/L%d: Error pTable=%d", __FUNCTION__, __LINE__, pTable);
+ return ACM_RC_INVALID_PATH;
+ }
+#endif
+
+ if(path_status_table[path_id].enabled == 0){
+ LOGE(APHAudioPathVolumeSet, "%s/L%d: Path %s(%d) is not enabled", __FUNCTION__, __LINE__, path, path_id);
+ return ACM_RC_PATH_NOT_ENABLED;
+ }
+
+ if(path_status_table[path_id].value == value){
+ LOGE(APHAudioPathVolumeSet, "%s/L%d: Path %s(%d), value=%d.", __FUNCTION__, __LINE__, path, path_id, value);
+ /* when modify the value of NVM and reload the modification, need to complete the following procedure. */
+ //return ACM_RC_INVALID_VOLUME_CHANGE;
+ }
+
+ LOGI(APHAudioPathVolumeSet,"%s/L%d:: path_status_table[%d].value = %d!", __FUNCTION__, __LINE__, path_id, path_status_table[path_id].value);
+
+ path_status_table[path_id].value = value;
+ volume = (unsigned char)(value & VOLUME_MASK);
+ volume = (volume + 5) /10;
+ index_volume = volume;
+ volume *= 10;
+
+ LOGI(APHAudioPathVolumeSet,"%s/L%d:: volume = %d!", __FUNCTION__, __LINE__, volume);
+
+ if (volume > MAX_VOLUME_INDEX) {
+ LOGE(APHAudioPathVolumeSet,"%s/L%d:: too big volume = %d!", __FUNCTION__, __LINE__, volume);
+ return ACM_RC_INVALID_VOLUME_CHANGE;
+ }
+
+#if defined(CODEC_PM805) || defined(CODEC_PM812) || defined(CODEC_NAU8810) || defined(CODEC_ALC5616)
+
+ if (0xFFFF != buffer.Rx_CodecGain[index_volume].RegAddr_1)
+ {
+ Component_NVM = buffer.Rx_CodecGain[index_volume].Component_1;
+ Address_NVM = buffer.Rx_CodecGain[index_volume].RegAddr_1;
+ Value_NVM = buffer.Rx_CodecGain[index_volume].RegVal_1;
+
+ configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
+ }
+
+ if (0xFFFF != buffer.Rx_CodecGain[index_volume].RegAddr_2)
+ {
+ Component_NVM = buffer.Rx_CodecGain[index_volume].Component_2;
+ Address_NVM = buffer.Rx_CodecGain[index_volume].RegAddr_2;
+ Value_NVM = buffer.Rx_CodecGain[index_volume].RegVal_2;
+
+ configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
+ }
+
+ if (0xFFFF != buffer.Rx_CodecGain[index_volume].RegAddr_3)
+ {
+ Component_NVM = buffer.Rx_CodecGain[index_volume].Component_3;
+ Address_NVM = buffer.Rx_CodecGain[index_volume].RegAddr_3;
+ Value_NVM = buffer.Rx_CodecGain[index_volume].RegVal_3;
+
+ configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
+ }
+
+ if (0xFFFF != buffer.Rx_CodecGain[index_volume].RegAddr_4)
+ {
+ Component_NVM = buffer.Rx_CodecGain[index_volume].Component_4;
+ Address_NVM = buffer.Rx_CodecGain[index_volume].RegAddr_4;
+ Value_NVM = buffer.Rx_CodecGain[index_volume].RegVal_4;
+
+ configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
+ }
+
+ LOGI(APHAudioPathVolumeSet,"Tx_CodecGain:: Component_1=0x%x, RegAddr_1=0x%x, RegVal_1=0x%x !\n",
+ buffer.Tx_CodecGain.Component_1, buffer.Tx_CodecGain.RegAddr_1, buffer.Tx_CodecGain.RegVal_1);
+
+ LOGI(APHAudioPathVolumeSet,"Tx_CodecGain:: Component_2=0x%x, RegAddr_2=0x%x, RegVal_2=0x%x !\n",
+ buffer.Tx_CodecGain.Component_2, buffer.Tx_CodecGain.RegAddr_2, buffer.Tx_CodecGain.RegVal_2);
+
+ LOGI(APHAudioPathVolumeSet,"Tx_CodecGain:: Component_3=0x%x, RegAddr_3=0x%x, RegVal_3=0x%x !\n",
+ buffer.Tx_CodecGain.Component_3, buffer.Tx_CodecGain.RegAddr_3, buffer.Tx_CodecGain.RegVal_3);
+
+ LOGI(APHAudioPathVolumeSet,"Tx_CodecGain:: Component_4=0x%x, RegAddr_4=0x%x, RegVal_4=0x%x !\n",
+ buffer.Tx_CodecGain.Component_4, buffer.Tx_CodecGain.RegAddr_4, buffer.Tx_CodecGain.RegVal_4);
+ //config Tx_CodecGain of acm_nvm.h here.
+ if (0xFFFF != buffer.Tx_CodecGain.RegAddr_1)
+ {
+ Component_NVM = buffer.Tx_CodecGain.Component_1;
+ Address_NVM = buffer.Tx_CodecGain.RegAddr_1;
+ Value_NVM = buffer.Tx_CodecGain.RegVal_1;
+
+ configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
+ }
+
+ if (0xFFFF != buffer.Tx_CodecGain.RegAddr_2)
+ {
+ Component_NVM = buffer.Tx_CodecGain.Component_2;
+ Address_NVM = buffer.Tx_CodecGain.RegAddr_2;
+ Value_NVM = buffer.Tx_CodecGain.RegVal_2;
+
+ configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
+ }
+
+ if (0xFFFF != buffer.Tx_CodecGain.RegAddr_3)
+ {
+ Component_NVM = buffer.Tx_CodecGain.Component_3;
+ Address_NVM = buffer.Tx_CodecGain.RegAddr_3;
+ Value_NVM = buffer.Tx_CodecGain.RegVal_3;
+
+ configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
+ }
+
+ if (0xFFFF != buffer.Tx_CodecGain.RegAddr_4)
+ {
+ Component_NVM = buffer.Tx_CodecGain.Component_4;
+ Address_NVM = buffer.Tx_CodecGain.RegAddr_4;
+ Value_NVM = buffer.Tx_CodecGain.RegVal_4;
+
+ configCodecGainfromNVM( Component_NVM, Address_NVM, Value_NVM);
+ }
+ return ACM_RC_OK;
+#else
+ return ACM_RC_OK;
+#endif
+}
+
+
+ACM_ReturnCode ACM_GetPathStatus(char *buff, unsigned int maxsize) {
+ unsigned int index = 0, size = 0, total = 0;
+ char *ptr = buff;
+
+ for(index = 0; index < APH_PATH_ID_CNT; index++){
+ //Prevent buff overwritten: reserve 100 bytes for this time
+ if(total > maxsize - 100)
+ return ACM_RC_INVALID_PARAMETER;
+
+ 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);
+ if(size > 0)
+ ptr += size;
+ else
+ return ACM_RC_INVALID_PARAMETER;
+ total += size;
+ }
+
+ return ACM_RC_OK;
+}
+
+unsigned int ACM_GetEnabledPathVolume(void)
+{
+ int i;
+ unsigned int enabled_path_id_Rx = INVALID_PATH_ID;
+ unsigned int enabled_path_id_Tx = INVALID_PATH_ID;
+ unsigned int enabled_volume_Rx = 80;//refer to the value: madev->voice_volume = 0.8f;
+ unsigned int enabled_mute_Tx = 0;
+
+ for (i=0; i<APH_PATH_ID_CNT; i++)
+ {
+ //save the enabled path.
+ if ( path_status_table[i].enabled)
+ {
+ if ((i != APH_PATH_ID_HIFIRECORDFROMMIC1) && (i != APH_PATH_ID_HIFIRECORDFROMHSMIC)
+ && (i !=APH_PATH_ID_VOICERECORDFROMMIC1) && (i !=APH_PATH_ID_VOICERECORDFROMHSMIC))
+ {
+ enabled_path_id_Rx = i;//record Rx path.
+ enabled_volume_Rx = path_status_table[i].value;
+ }
+ else
+ {
+ enabled_path_id_Tx = i;//record Tx path.
+ enabled_mute_Tx = path_status_table[i].mute;
+ }
+ }
+ }
+
+ LOGI(ACM_GetEnabledPathVolume, "%s/L%d: enabled_path_id_Rx=%d, enabled_path_id_Tx=%d, enabled_volume_Rx=%d, enabled_mute_Tx=%d,",
+ __FUNCTION__, __LINE__,enabled_path_id_Rx,enabled_path_id_Tx, enabled_volume_Rx, enabled_mute_Tx);
+
+ return enabled_volume_Rx;
+}
+
+ACM_ReturnCode ACM_GetPathDirection(const char *path, unsigned char *path_direction) {
+ return _get_path_direction(path, path_direction);
+}
+
+ACM_ReturnCode APHGetMSAGain(const char *out_path, const char *path, unsigned char *volume, unsigned short id, signed short *gain, signed short *sidetone_gain) {
+
+#if defined(CODEC_PM805) || defined(CODEC_PM812) || defined(CODEC_NAU8810) || defined(CODEC_ALC5616)
+ int path_id = INVALID_PATH_ID;
+ AC_IPC_Package package;
+ ACMCodec_GainT buffer;
+ unsigned char Volume_value;
+ unsigned char index_volume;
+ AUDIO_PROFILE_ID cur_Profile_id = HIFI_HANDSET;
+
+ memset(&package, 0x00, sizeof(AC_IPC_Package));
+ memset(&buffer, 0x00, sizeof(ACMCodec_GainT));
+
+ LOGI(APHGetMSAGain, "%s/L%d: out_path=%s, path=%s, volume=%d, id=%d", __FUNCTION__, __LINE__, out_path, path, *volume, id);
+
+ //If not equal between out_path and path, it is input device, we need to use out_path to get gain from NVM.
+ path_id = _get_path_id(out_path);
+ if(path_id == INVALID_PATH_ID)
+ {
+ LOGE(APHGetMSAGain, "%s: ERROR: can not find matched path id", __FUNCTION__);
+ return ACM_RC_INVALID_PATH;
+ }
+
+ //RX path is mapping to PROFILE.
+ switch (path_id)
+ {
+ case APH_PATH_ID_HIFIPLAYTOEARPHONE:
+ cur_Profile_id = HIFI_HANDSET;
+ break;
+
+ case APH_PATH_ID_HIFIPLAYTOSPKR:
+ cur_Profile_id = HIFI_SPEAKER;
+ break;
+
+ case APH_PATH_ID_HIFIPLAYTOHP:
+ cur_Profile_id = HIFI_HEADSET;
+ break;
+
+ case APH_PATH_ID_VOICEPLAYTOEARPHONE:
+ cur_Profile_id = VC_HANDSET;
+ break;
+
+ case APH_PATH_ID_VOICEPLAYTOSPKR:
+ cur_Profile_id = VC_HANDSFREE;
+ break;
+
+ case APH_PATH_ID_VOICEPLAYTOHP:
+ cur_Profile_id = VC_HEADSET;
+ break;
+
+ default:
+ LOGI(APHGetMSAGain, "%s/L%d: PATH ID=%d, PATH is %s.", __FUNCTION__, __LINE__, path_id, path);
+ break;
+ }
+
+ package.type = AUDIO_NVM_GetGainConfigure;
+ package.body.d1 = 0;
+ package.body.d2 = cur_Profile_id; //path ID (unsigned short)
+ package.ptr = &buffer;
+
+ NVM_Calibration_IPC(&package);
+
+ Volume_value = (unsigned char)((*volume) & VOLUME_MASK);
+ Volume_value = (Volume_value + 5) /10;
+ index_volume = Volume_value;
+ Volume_value *= 10;
+
+ if (strcmp(out_path, path))
+ {//MIC, HSMIC...
+ *gain = buffer.Tx_DSPGain;
+ *sidetone_gain = 0;
+ LOGI(APHGetMSAGain,"APHGetMSAGain::profile=%d, Tx DSP gain = 0x%hx, sidetone = 0x%hx!", buffer.Profile_id, *gain, *sidetone_gain);
+ }
+ else
+ {//EARPHONE, SPEAKER...
+ *gain = buffer.Rx_DSPGain[index_volume];
+ *sidetone_gain = buffer.Rx_DSPSideToneGain;
+ LOGI(APHGetMSAGain,"APHGetMSAGain::profile=%d, Rx DSP gain = 0x%hx, sidetone = 0x%hx!", buffer.Profile_id, *gain, *sidetone_gain);
+ }
+
+ return ACM_RC_OK;
+
+#else
+
+ *gain = 0;
+ *sidetone_gain = 0x8080;//0x8080=disable sidetone
+ LOGI(APHGetMSAGain,"Not supported codec! APHGetMSAGain:: DSP gain = 0x%hx, sidetone = 0x%hx!", *gain, *sidetone_gain);
+ return ACM_RC_OK;
+
+#endif
+
+}
+
+#ifdef PXA1826_AUDIO
+ACM_ReturnCode APHSetMSAGain(AC_Digital_Gain *gain) {
+ VolumeCtlMsg volume_cmd;
+ int ioctl_fd;
+
+ // If no voice path actived, will not configure DSP
+ if((gain->path_direction_Rx > 1) || (gain->path_direction_Tx > 1))
+ {
+ LOGI(APHSetMSAGain, "no voice path actived, will not configure DSP: Rx=%d,Tx=%d", gain->path_direction_Rx, gain->path_direction_Tx);
+ return ACM_RC_OK;
+ }
+
+ ioctl_fd = open("/dev/audiostub_ctl", O_RDONLY);
+ if(ioctl_fd < 0)
+ {
+ LOGI(APHSetMSAGain, "failed to open audiostub_ctl: %s", strerror(errno));
+ return ACM_RC_PATH_NOT_ENABLED;
+ }
+
+ //Rx
+ memset(&volume_cmd, 0, sizeof(volume_cmd));
+ volume_cmd.direction = gain->path_direction_Rx;
+ volume_cmd.gain = gain->digital_gain_Rx;
+ volume_cmd.misc_volume = gain->volume_Rx;
+ if(ioctl(ioctl_fd, AUDIOSTUB_VOLUMECTL, &volume_cmd) < 0)
+ {
+ LOGI(APHSetMSAGain, "audio_stub ioctl error: %s", strerror(errno));
+ close(ioctl_fd);
+ return ACM_RC_INVALID_PARAMETER;
+ }
+
+ //Tx
+ memset(&volume_cmd, 0, sizeof(volume_cmd));
+ volume_cmd.direction = gain->path_direction_Tx;
+ volume_cmd.gain = gain->digital_gain_Tx;
+ volume_cmd.misc_volume = gain->volume_Tx;
+ if(ioctl(ioctl_fd, AUDIOSTUB_VOLUMECTL, &volume_cmd) < 0)
+ {
+ LOGI(APHSetMSAGain, "audio_stub ioctl error: %s", strerror(errno));
+ close(ioctl_fd);
+ return ACM_RC_INVALID_PARAMETER;
+ }
+
+ //SideTone
+ memset(&volume_cmd, 0, sizeof(volume_cmd));
+ volume_cmd.direction = gain->path_direction_SideTone;
+ volume_cmd.gain = gain->digital_gain_SideTone;
+ volume_cmd.misc_volume = gain->volume_SideTone;
+ if(ioctl(ioctl_fd, AUDIOSTUB_VOLUMECTL, &volume_cmd) < 0)
+ {
+ LOGI(APHSetMSAGain, "audio_stub ioctl error: %s", strerror(errno));
+ close(ioctl_fd);
+ return ACM_RC_INVALID_PARAMETER;
+ }
+
+ close(ioctl_fd);
+ LOGI(APHSetMSAGain, "APHSetMSAGain success!");
+
+ return ACM_RC_OK;
+}
+#endif
+
+#ifdef TARGET_mmp_asr1901_KSTR901
+extern int audio_dsp_send_ve(void* ve);
+
+void ACM_SendVEtoADSP(void) {
+ AC_IPC_Package package;
+ EnhanceParmsT buffer;
+
+ memset(&package, 0x00, sizeof(AC_IPC_Package));
+ memset(&buffer, 0x00, sizeof(EnhanceParmsT));
+
+ LOGI(ACM_SendVEtoADSP, "%s/%d\n", __FUNCTION__, __LINE__);
+
+ package.type = AUDIO_NVM_GetVEConfigure;
+ package.body.d1 = 0;
+ package.body.d2 = 0;
+ package.ptr = &buffer;
+
+ NVM_Calibration_IPC(&package);
+ audio_dsp_send_ve(&buffer);
+}
+#endif
+
+ACM_ReturnCode ACM_GetEnabledPathId(int *path_id_Rx, int *path_id_Tx, int *volume_Rx, int *mute_Tx)
+{
+ int i;
+
+ int enabled_path_id_Rx = INVALID_PATH_ID;
+ int enabled_path_id_Tx = INVALID_PATH_ID;
+ int enabled_volume_Rx = 0;
+ int enabled_mute_Tx = 0;
+
+ for (i=0; i<APH_PATH_ID_CNT; i++)
+ {
+ //save the enabled path.
+ if ( path_status_table[i].enabled)
+ {
+ if ((i != APH_PATH_ID_HIFIRECORDFROMMIC1) && (i != APH_PATH_ID_HIFIRECORDFROMHSMIC)
+ && (i !=APH_PATH_ID_VOICERECORDFROMMIC1) && (i !=APH_PATH_ID_VOICERECORDFROMHSMIC))
+ {
+ enabled_path_id_Rx = i;//record Rx path.
+ enabled_volume_Rx = path_status_table[i].value;
+ }
+ else
+ {
+ enabled_path_id_Tx = i;//record Tx path.
+ enabled_mute_Tx = path_status_table[i].mute;
+ }
+ }
+ }
+
+ LOGI(ACM_GetEnabledPathId, "%s/L%d: enabled_path_id_Rx=%d, enabled_path_id_Tx=%d, enabled_volume_Rx=%d, enabled_mute_Tx=%d,",
+ __FUNCTION__, __LINE__,enabled_path_id_Rx,enabled_path_id_Tx, enabled_volume_Rx, enabled_mute_Tx);
+
+ *path_id_Rx = enabled_path_id_Rx;
+ *path_id_Tx = enabled_path_id_Tx;
+ *volume_Rx = enabled_volume_Rx;
+ *mute_Tx = enabled_mute_Tx;
+
+ return ACM_RC_OK;
+}
+
+ACM_ReturnCode ACM_ReloadCalibrationData(void) {
+ char tmp_buffer[PATHSTATUS_MAX] = {0};
+ int i = 0, value;
+ int path_id_Rx = INVALID_PATH_ID;
+ int path_id_Tx = INVALID_PATH_ID;
+ int volume_Rx = 0;
+ char mute_Tx = 0;
+ AUDIO_PROFILE_ID cur_Profile_id = HIFI_HANDSET;
+ AC_IPC_Package package;
+
+ /*
+ First: send message "AUDIO_NVM_ReloadCalibrationData" to NVM server, trigger reload nvm.
+ No matter whether there is enabled path.
+ */
+ memset(&package, 0x00, sizeof(AC_IPC_Package));
+ package.type = AUDIO_NVM_ReloadCalibrationData;
+ package.body.d1 = 0;
+ package.body.d2 = 0;
+ package.ptr = &value;
+ NVM_Calibration_IPC(&package);
+
+ //Second: get path status.
+ if (ACM_GetPathStatus(tmp_buffer, PATHSTATUS_MAX) != ACM_RC_OK)
+ {
+ LOGE(ACM_ReloadCalibrationData, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
+ return ACM_RC_PATH_CONFIG_NOT_EXIST;
+ }
+
+ //list the path status, before ReloadCalibrationData
+ LOGI(ACM_ReloadCalibrationData, "before ReloadCalibrationData, record the path status, current every path status is:\n%s.......", tmp_buffer);
+
+ for (i=0; i<APH_PATH_ID_CNT; i++)
+ {
+ //save the enabled path.
+ if ( path_status_table[i].enabled)
+ {
+ if ((i != APH_PATH_ID_HIFIRECORDFROMMIC1) && (i != APH_PATH_ID_HIFIRECORDFROMHSMIC)
+ && (i !=APH_PATH_ID_VOICERECORDFROMMIC1) && (i !=APH_PATH_ID_VOICERECORDFROMHSMIC))
+ {
+ path_id_Rx = i;//record Rx path.
+ volume_Rx = path_status_table[i].value;
+ }
+ else
+ {
+ path_id_Tx = i;//record Tx path.
+ mute_Tx = path_status_table[i].mute;
+ }
+ }
+ }
+
+ if ((INVALID_PATH_ID == path_id_Rx) || (INVALID_PATH_ID == path_id_Tx))
+ {
+ LOGI(ACM_ReloadCalibrationData, "%s/L%d: no enabled path.", __FUNCTION__, __LINE__);
+ return ACM_RC_OK;
+ }
+
+ LOGI(ACM_ReloadCalibrationData, "%s/L%d: actived path:Rx path:%s, Tx path:%s",
+ __FUNCTION__, __LINE__, AUDIO_PATH_ID_MAPPING[path_id_Rx].PathName, AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName);
+
+ if ((APHAudioPathCheck(AUDIO_PATH_ID_MAPPING[path_id_Rx].PathName, AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName) != ACM_RC_OK_HIFI_MATCHED)
+ && (APHAudioPathCheck(AUDIO_PATH_ID_MAPPING[path_id_Rx].PathName, AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName) != ACM_RC_OK_VOICE_MATCHED))
+ {
+ LOGE(ACM_ReloadCalibrationData, "%s/L%d: Rx path is not matched with Tx path.", __FUNCTION__, __LINE__);
+ return ACM_RC_PATH_CONFIG_NOT_EXIST;
+ }
+
+ //RX path is mapping to PROFILE.
+ switch (path_id_Rx)
+ {
+ case APH_PATH_ID_HIFIPLAYTOEARPHONE:
+ cur_Profile_id = HIFI_HANDSET;
+ break;
+
+ case APH_PATH_ID_HIFIPLAYTOSPKR:
+ cur_Profile_id = HIFI_SPEAKER;
+ break;
+
+ case APH_PATH_ID_HIFIPLAYTOHP:
+ cur_Profile_id = HIFI_HEADSET;
+ break;
+
+ case APH_PATH_ID_VOICEPLAYTOEARPHONE:
+ cur_Profile_id = VC_HANDSET;
+ break;
+
+ case APH_PATH_ID_VOICEPLAYTOSPKR:
+ cur_Profile_id = VC_HANDSFREE;
+ break;
+
+ case APH_PATH_ID_VOICEPLAYTOHP:
+ cur_Profile_id = VC_HEADSET;
+ break;
+
+ default:
+ LOGI(ACM_ReloadCalibrationData, "%s/L%d.", __FUNCTION__, __LINE__);
+ break;
+ }
+
+ LOGI(ACM_ReloadCalibrationData,"AUDIO_NVM_ReloadCalibrationData:: profile=%d, sizeof(AUDIO_PROFILE_ID)=%d!",
+ cur_Profile_id, sizeof(AUDIO_PROFILE_ID));
+
+ //Third:enable the saved path using new config.
+ APHAudioPathDisable(AUDIO_PATH_ID_MAPPING[path_id_Rx].PathName);
+ APHAudioPathDisable(AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName);
+
+ ACMAudioPathEnable(AUDIO_PATH_ID_MAPPING[path_id_Rx].PathName, volume_Rx);
+ ACMAudioPathEnable(AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName, volume_Rx);
+ APHAudioPathMute(AUDIO_PATH_ID_MAPPING[path_id_Tx].PathName, mute_Tx);
+
+ //Forth: List the path status.
+ memset(tmp_buffer, 0x00, sizeof(tmp_buffer));
+
+ if (ACM_GetPathStatus(tmp_buffer, PATHSTATUS_MAX) != ACM_RC_OK)
+ {
+ LOGE(ACM_ReloadCalibrationData, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
+ return ACM_RC_PATH_CONFIG_NOT_EXIST;
+ }
+
+ //After recover the enabled path, list the path status
+ LOGI(ACM_ReloadCalibrationData, "After recover the enabled path, list the path status is:%s.......", tmp_buffer);
+
+ return ACM_RC_OK;
+}
+
+void ACM_enable_headset_detection_ALC5616(void)
+{
+#ifdef TARGET_mmp_asr1901_KSTR901
+ system("echo 1 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616-headset/enable_headset_detection");
+#else
+ system("echo 1 > /sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616-headset/enable_headset_detection");
+#endif
+ return;
+}
+
+void ACM_APHInit(void) {
+#ifdef PXA1826_AUDIO
+ int ret = 0;
+ int err, ioctl_fd, status = 0;
+#endif
+ int value;
+ AC_IPC_Package package;
+
+ if (0 == get_debug_mode())
+ {
+ /* 1:on; 0:off, default. if g_audio_if_debug_mode is on, no need to send msg to NVMProxy. */
+
+ //Reload AP Audio NVM
+ package.type = AUDIO_NVM_ReloadCalibrationData;
+ package.body.d1 = 0;
+ package.body.d2 = 0;
+ package.ptr = &value;
+ NVM_Calibration_IPC(&package);
+ }
+
+ //reset components status
+ if(acm_codec_connected == TRUE){
+ _reset_components_status();
+ _reset_components_registers();
+ }
+
+ /*
+ * From audio_stub, get the properties of nb/wb, master/slave
+ */
+#ifdef PXA1826_AUDIO
+ ioctl_fd = open("/dev/audiostub_ctl", O_RDONLY);
+ if (ioctl_fd < 0) {
+ err = errno;
+ ALOGE(ACM_APHInit9, "failed to open audiostub_ctl:%s\n", strerror(err));
+ return;
+ }
+
+ ret = ioctl(ioctl_fd, AUDIOSTUB_GET_STATUS, &status);
+ if (ret < 0) {
+ ALOGE(ACM_APHInit10, "Warning, audio_stub ioctl error: %s", strerror(errno));
+ }
+ modem_is_wb = IS_WB(status);
+ modem_is_master = IS_PCM_MASTER(status);
+
+ LOGI(ACM_APHInit, "%s/L%d: modem_is_wb=%d, modem_is_master=%d", __FUNCTION__, __LINE__, modem_is_wb, modem_is_master);
+
+ //close the file after got status report
+ close(ioctl_fd);
+#endif
+}
+
+void ACM_APHDeInit(void) {
+}
+
+
+/* Audio uses PROPERTY_AUDIO_CODEC which is not created by PXA1826 init
+ * Call from ACMInit() to set property with default value "1"
+ * depending upon the AUDIO package is better than in init.rc
+ * (No other setprop are present for now)
+ */
+void ACM_Init_Property(void)
+{
+ char property_value[PROPERTY_VALUE_MAX];
+ int i = property_get(PROPERTY_AUDIO_CODEC, property_value, NULL);
+ if (i <= 0) {
+ LOGD(ACM_Init_Property, "Not found %s. Create with default value=%d", PROPERTY_AUDIO_CODEC, (modem_is_master == 0)?1:0);
+ if(modem_is_master == 0)
+ property_set(PROPERTY_AUDIO_CODEC, "1"); //persist.audio.codecmaster = 1
+ else
+ property_set(PROPERTY_AUDIO_CODEC, "0"); //persist.audio.codecmaster = 0
+ }
+ else
+ LOGD(ACM_Init_Property, "Found %s. value=%s", PROPERTY_AUDIO_CODEC, property_value);
+}
+