ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/services/audio/libacm/acm/src/ac_thread.c b/marvell/services/audio/libacm/acm/src/ac_thread.c
new file mode 100644
index 0000000..23737bf
--- /dev/null
+++ b/marvell/services/audio/libacm/acm/src/ac_thread.c
@@ -0,0 +1,864 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * ac_thread.c: enabled for AUDIO_CALIBRATION only
+ */
+
+#define LOG_TAG "ac_thread"
+//#define LOG_NDEBUG 0
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include "audioCalibration.h"
+#include "acm_aph.h"
+#include "acm_param.h"
+#include "ac_thread.h"
+#include "vcm.h"
+#include "adsp_ve.h"
+
+#define REG_BUFFER_SIZE 100
+#define PHY_VERSION_LEN 36
+static pthread_t ACM_Calibration_Server;
+
+int NVM_Calibration_IPC(AC_IPC_Package *package);
+void get_msa_gain_by_path_name(const char * out_path_name, const char * path_name, unsigned char volume,
+ signed char *ret_gain, signed char *ret_gain_wb, signed char *ret_sidetone_gain, signed char *ret_sidetone_gain_wb, bool use_extra_vol);
+ACM_ReturnCode AC_ReloadCalibrationData(AC_Digital_Gain *gain);
+void AC_EnablePath(AC_IPC_Package_Body *path_para, AC_Digital_Gain *gain);
+void AC_DisablePath(AC_IPC_Package_Body *path_para);
+void AC_MutePath(AC_IPC_Package_Body *path_para);
+void AC_SetPathVolume(AC_IPC_Package_Body *path_para, AC_Digital_Gain *gain);
+void AC_SwitchPath(AC_IPC_Package_Body *path_para, AC_Digital_Gain *gain);
+
+extern audio_mode_t ACMGetAudioMode(void);
+extern void get_pcm_config(int *p_role, int *p_rate);
+
+static int fd_server = -1;
+static int clientfd_server = -1;
+
+//client which send message to NVM server.
+int NVM_Calibration_IPC(AC_IPC_Package *package)
+{
+ int fd, len, value;
+ struct sockaddr_un un;
+
+ /* create a UNIX domain stream socket */
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
+ LOGE(NVM_Calibration_IPC, "[Audio NVM Calibration][%s][%d][create socket fail]\n", __FUNCTION__, __LINE__);
+ return 1;
+ }
+
+ /* fill socket address structure with server's address */
+ memset(&un, 0, sizeof(un));
+ un.sun_family = AF_UNIX;
+ switch (package->type)
+ {
+ case AUDIO_NVM_GetGainConfigure:
+ case AUDIO_NVM_ReloadCalibrationData:
+ case AUDIO_NVM_GetVEConfigure:
+ strcpy(un.sun_path, NVM_CALIBRATION_SOCKET);
+ len = offsetof(struct sockaddr_un, sun_path) + strlen(NVM_CALIBRATION_SOCKET);
+ break;
+
+ default:
+ LOGE(NVM_Calibration_IPC, "[Audio NVM Calibration Client][%d][IPC type error]\n", __LINE__);
+ close(fd);
+ return 3;
+ }
+ if (connect(fd, (struct sockaddr *)&un, len) < 0) {
+ LOGE(NVM_Calibration_IPC,"[Audio NVM Calibration Client][%d][connect fail][error %d(%s)]\n", __LINE__,errno, strerror(errno));
+ close(fd);
+ return 4;
+ }
+
+ LOGI(NVM_Calibration_IPC,"[Audio NVM Calibration Client][%d]-[send type:%d]-[d1:%d][d2:%d][d3:%d][d4:%d]\n",
+ __LINE__,
+ package->type, package->body.d1, package->body.d2, package->body.d3, package->body.d4);
+
+ LOGI(NVM_Calibration_IPC,"NVM_Calibration_IPC:: un.sun_path=%s!", un.sun_path);
+
+ if(write(fd, package, sizeof(AC_IPC_Package)) == -1) {
+ LOGE(NVM_Calibration_IPC,"[Audio NVM Calibration Client][%d][write fail]\n", __LINE__);
+ close(fd);
+ return 5;
+ }
+
+ /* get data from server when necessary */
+ switch (package->type)
+ {
+ case AUDIO_NVM_GetGainConfigure:
+ if(read(fd, package->ptr, sizeof(ACMCodec_GainT)) == -1) {
+ LOGE(NVM_Calibration_IPC,"[Audio NVM Calibration Client][%d][read fail]\n", __LINE__);
+ close(fd);
+ return 11;
+ }
+ break;
+
+ case AUDIO_NVM_ReloadCalibrationData:
+ if(read(fd, &value, sizeof(int)) == -1) {
+ LOGE(NVM_Calibration_IPC,"[Audio NVM Calibration Client][%d][read fail]\n", __LINE__);
+ close(fd);
+ return 12;
+ }
+ else {
+ if(value == -1) {
+ LOGI(NVM_Calibration_IPC,"[Audio NVM Calibration Client][%d][AUDIO_NVM_ReloadCalibrationData Fail: no codec compiled]\n", __LINE__);
+ }
+ else if(value == 0) {
+ LOGI(NVM_Calibration_IPC,"[Audio NVM Calibration Client][%d][AUDIO_NVM_ReloadCalibrationData Success: reload existing file]\n", __LINE__);
+ }
+ else if(value == 1) {
+ LOGI(NVM_Calibration_IPC,"[Audio NVM Calibration Client][%d][AUDIO_NVM_ReloadCalibrationData Success: create new file]\n", __LINE__);
+ }
+ }
+ break;
+
+ case AUDIO_NVM_GetVEConfigure:
+ if(read(fd, package->ptr, sizeof(EnhanceParmsT)) == -1) {
+ LOGE(NVM_Calibration_IPC,"[Audio NVM Calibration Client][%d][read fail]\n", __LINE__);
+ close(fd);
+ return 13;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+// get MSA gain from ACM NVM according to device path name
+void get_msa_gain_by_path_name(const char * out_path_name, const char * path_name, unsigned char volume,
+ signed char *ret_gain, signed char *ret_gain_wb, signed char *ret_sidetone_gain, signed char *ret_sidetone_gain_wb, bool use_extra_vol)
+{
+ int extra_volume = (use_extra_vol ? MSA_GAIN_EXTRA_MODE : MSA_GAIN_NORMAL_MODE);
+ ACM_MsaGain msa_gain = {0};
+ unsigned int size = sizeof(ACM_MsaGain);
+
+ msa_gain.volume = volume;
+ msa_gain.gain = 0;
+ msa_gain.wbGain = 0;
+ msa_gain.path_direction = 0;
+
+ // fix to VC mode here. only VC have msa gain
+ msa_gain.out_path_name = out_path_name;
+ msa_gain.path_name = path_name;
+
+ if (ACMSetParameter(ACM_MSA_GAIN_MODE, NULL, extra_volume) != ACM_RC_OK) {
+ LOGE(get_msa_gain_by_path_name, "set output msa gain mode failed, use the default normal mode ");
+ }
+
+ if (ACMGetParameter(ACM_MSA_GAIN, &msa_gain, &size) != ACM_RC_OK) {
+ LOGE(get_msa_gain_by_path_name, "get output msa gain failed, use default gain.");
+ }
+
+ *ret_gain = msa_gain.gain;
+ *ret_gain_wb = msa_gain.wbGain;
+ *ret_sidetone_gain = msa_gain.sidetone_gain;
+ *ret_sidetone_gain_wb = msa_gain.sidetone_wbGain;
+}
+
+//handle the message from NVM server, and recover the status using new config.
+ACM_ReturnCode AC_ReloadCalibrationData(AC_Digital_Gain *gain) {
+
+ int Rx_path_id = 0xFF;
+ int Tx_path_id = 0xFF;
+ int volume_Rx = 0;
+ int mute_Tx = 0;
+ const char* Rx_pathname = NULL;
+ const char* Tx_pathname = NULL;
+
+ signed char input_gain = 0;
+ signed char input_gain_wb = 0;
+ signed char output_gain = 0;
+ signed char output_gain_wb = 0;
+ signed char rx_sidetone_gain = 0;
+ signed char rx_sidetone_gain_wb = 0;
+ signed char tx_sidetone_gain = 0;
+ signed char tx_sidetone_gain_wb = 0;
+ unsigned char vc_output_vol = 0;
+ bool use_extra_vol = 0;
+
+ //Default: notify audioCalibration.c not to configure DSP gain
+ gain->path_direction_Rx = VCM_PATH_NOT_CONNECTED;
+ gain->path_direction_Tx = VCM_PATH_NOT_CONNECTED;
+
+ ACM_ReloadCalibrationData();
+
+ //get active path
+ ACM_GetEnabledPathId(&Rx_path_id, &Tx_path_id, &volume_Rx, &mute_Tx);
+
+ if ((0xFF == Rx_path_id) || (0xFF == Tx_path_id))
+ {
+ LOGE( AC_ReloadCalibrationData, "%s/L%d: no enabled path.",__FUNCTION__, __LINE__);
+ return ACM_RC_OK;
+ }
+
+ LOGI( AC_ReloadCalibrationData, "%s/L%d: Rx_path_id=%d, Tx_path_id=%d, volume_Rx=%d, mute_Tx=%d.",
+ __FUNCTION__, __LINE__, Rx_path_id, Tx_path_id, volume_Rx, mute_Tx);
+
+ //HIFI has no digital gain
+ if (ACM_RC_OK_VOICE_MATCHED != APHAudioPathCheckPathId(Rx_path_id, Tx_path_id))
+ {
+ LOGI( AC_ReloadCalibrationData, "%s/L%d: current mode is AUDIO_MODE_NORMAL.",__FUNCTION__, __LINE__);
+ return ACM_RC_OK;
+ }
+
+ Rx_pathname = ACM_GetPathName(Rx_path_id);
+ Tx_pathname = ACM_GetPathName(Tx_path_id);
+
+ if ((NULL == Rx_pathname) || (NULL == Tx_pathname))
+ {
+ LOGE( AC_ReloadCalibrationData, "%s/L%d: RX or TX pathname is NULL.",__FUNCTION__, __LINE__);
+ return ACM_RC_OK;
+ }
+
+ vc_output_vol = volume_Rx;
+
+ get_msa_gain_by_path_name(Rx_pathname, Tx_pathname, 100, &input_gain, &input_gain_wb, &tx_sidetone_gain, &tx_sidetone_gain_wb, use_extra_vol);
+ get_msa_gain_by_path_name(Rx_pathname, Rx_pathname, vc_output_vol, &output_gain, &output_gain_wb, &rx_sidetone_gain, &rx_sidetone_gain_wb, use_extra_vol);
+
+ LOGI(AC_ReloadCalibrationData, "%s/L%d: input_gain=0x%x, input_gain_wb=0x%x, output_gain=0x%x, output_gain_wb=0x%x.use_extra_vol=%d.\n",
+ __FUNCTION__, __LINE__, input_gain, input_gain_wb, output_gain, output_gain_wb, use_extra_vol);
+
+ gain->path_direction_Rx = VCM_PATH_OUT;
+ gain->digital_gain_Rx = output_gain | (output_gain_wb << 8);
+ gain->volume_Rx = vc_output_vol;
+
+ gain->path_direction_Tx = VCM_PATH_IN;
+ gain->digital_gain_Tx = input_gain | (input_gain_wb << 8);
+ gain->volume_Tx = vc_output_vol;
+
+ gain->path_direction_SideTone = VCM_PATH_SIDETONE;
+ gain->digital_gain_SideTone = rx_sidetone_gain | (rx_sidetone_gain_wb << 8);
+ gain->volume_SideTone = vc_output_vol;
+
+ LOGI(AC_ReloadCalibrationData, "%s/L%d: digital_gain_Rx=0x%x, volume_Rx=%d, digital_gain_Tx=0x%x, volume_Tx=%d, digital_gain_SideTone=%d.\n",
+ __FUNCTION__, __LINE__, gain->digital_gain_Rx, gain->volume_Rx, gain->digital_gain_Tx, gain->volume_Tx, gain->digital_gain_SideTone);
+
+
+ return ACM_RC_OK;
+}
+
+ACM_ReturnCode APHReloadNvm(void) {
+ AC_Digital_Gain gain;
+ ACM_ReturnCode ret;
+
+ LOGI(APHReloadNvm, "%s/L%d: ReloadCalibrationData", __FUNCTION__, __LINE__);
+ memset(&gain, 0x00, sizeof(AC_Digital_Gain));
+
+ ret = AC_ReloadCalibrationData(&gain);
+ if (ACM_RC_OK != ret) {
+ LOGI(APHReloadNvm, "%s/L%d: ReloadCalibrationData fail.", __FUNCTION__, __LINE__);
+ return ret;
+ }
+
+#ifdef PXA1826_AUDIO
+ ret = APHSetMSAGain(&gain);
+ if (ACM_RC_OK != ret) {
+ LOGI(APHReloadNvm, "%s/L%d: ReloadCalibrationData fail.", __FUNCTION__, __LINE__);
+ return ret;
+ }
+#endif
+
+ return ACM_RC_OK;
+}
+
+/*
+Function: enable the path which is disabled status.
+path_para.d1: Rx_path_id
+path_para.d2: Tx_path_id
+path_para.d3: volume
+ */
+void AC_EnablePath(AC_IPC_Package_Body *path_para, AC_Digital_Gain *gain)
+{
+ int Rx_path_id = path_para->d1;
+ int Tx_path_id = path_para->d2;
+ unsigned int Volume = path_para->d3;
+
+ signed char input_gain = 0;
+ signed char input_gain_wb = 0;
+ signed char output_gain = 0;
+ signed char output_gain_wb = 0;
+ signed char rx_sidetone_gain = 0;
+ signed char rx_sidetone_gain_wb = 0;
+ signed char tx_sidetone_gain = 0;
+ signed char tx_sidetone_gain_wb = 0;
+ unsigned char vc_output_vol = 0;
+ bool use_extra_vol = 0;
+
+ const char* Rx_pathname = ACM_GetPathName(Rx_path_id);
+ const char* Tx_pathname = ACM_GetPathName(Tx_path_id);
+
+ if ((NULL == Rx_pathname) || (NULL == Tx_pathname))
+ {
+ LOGE( AC_EnablePath, "%s/L%d: RX or TX pathname is NULL.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ vc_output_vol = Volume;
+
+ LOGI( AC_EnablePath, "%s/L%d: Rx_path_id = %d, Rx_pathname =%s, Tx_path_id = %d, Tx_pathname = %s, Volume =%d",
+ __FUNCTION__, __LINE__, Rx_path_id, Rx_pathname, Tx_path_id, Tx_pathname, Volume);
+
+ if ((ACM_RC_OK_HIFI_MATCHED != APHAudioPathCheck (Rx_pathname, Tx_pathname))
+ && (ACM_RC_OK_VOICE_MATCHED != APHAudioPathCheck (Rx_pathname, Tx_pathname)))
+ {
+ LOGE( AC_EnablePath, "%s/L%d: RX is not matched with TX.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ //Disable all enabled path, otherwise there may be several enabled path.
+ APHDisableAllPath();
+
+ ACMAudioPathEnable(Rx_pathname, Volume);
+ ACMAudioPathEnable(Tx_pathname, Volume);
+
+ //get the gain for voice
+ if (ACM_RC_OK_HIFI_MATCHED == APHAudioPathCheck (Rx_pathname, Tx_pathname))
+ {
+ LOGI( AC_EnablePath, "%s/L%d: RX is matched with TX about HIFI. Not need to get digital gain.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ get_msa_gain_by_path_name(Rx_pathname, Tx_pathname, 100, &input_gain, &input_gain_wb, &tx_sidetone_gain, &tx_sidetone_gain_wb, use_extra_vol);
+ get_msa_gain_by_path_name(Rx_pathname, Rx_pathname, vc_output_vol, &output_gain, &output_gain_wb, &rx_sidetone_gain, &rx_sidetone_gain_wb, use_extra_vol);
+
+ LOGI(AC_EnablePath, "%s/L%d: input_gain= 0x%x, input_gain_wb=0x%x, output_gain=0x%x, output_gain_wb=0x%x.use_extra_vol=%d.\n",
+ __FUNCTION__, __LINE__, input_gain, input_gain_wb, output_gain, output_gain_wb, use_extra_vol);
+
+ gain->path_direction_Rx = VCM_PATH_OUT;
+ gain->digital_gain_Rx = output_gain | (output_gain_wb << 8);
+ gain->volume_Rx = vc_output_vol;
+
+ gain->path_direction_Tx = VCM_PATH_IN;
+ gain->digital_gain_Tx = input_gain | (input_gain_wb << 8);
+ gain->volume_Tx = vc_output_vol;
+
+ gain->path_direction_SideTone = VCM_PATH_SIDETONE;
+ gain->digital_gain_SideTone = rx_sidetone_gain | (rx_sidetone_gain_wb << 8);
+ gain->volume_SideTone = vc_output_vol;
+
+ LOGI(AC_EnablePath, "%s/L%d: digital_gain_Rx=0x%x, volume_Rx=%d, digital_gain_Tx=0x%x, volume_Tx=%d, digital_gain_SideTone=%d.\n",
+ __FUNCTION__, __LINE__, gain->digital_gain_Rx, gain->volume_Rx, gain->digital_gain_Tx, gain->volume_Tx, gain->digital_gain_SideTone);
+
+}
+
+/*
+Function: Disable the path which is enabled.
+path_para.d1: Rx_path_id
+path_para.d2: Tx_path_id
+ */
+void AC_DisablePath(AC_IPC_Package_Body *path_para) {
+ int Rx_path_id = path_para->d1;
+ int Tx_path_id = path_para->d2;
+
+ const char* Rx_pathname = ACM_GetPathName(Rx_path_id);
+ const char* Tx_pathname = ACM_GetPathName(Tx_path_id);
+
+ if ((NULL == Rx_pathname) || (NULL == Tx_pathname))
+ {
+ LOGE( AC_DisablePath, "%s/L%d: RX or TX pathname is NULL.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ if ((ACM_RC_OK_HIFI_MATCHED != APHAudioPathCheck (Rx_pathname, Tx_pathname))
+ && (ACM_RC_OK_VOICE_MATCHED != APHAudioPathCheck (Rx_pathname, Tx_pathname)))
+ {
+ LOGE( AC_DisablePath, "%s/L%d: RX is not matched with TX.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ ACMAudioPathDisable(Rx_pathname);
+ ACMAudioPathDisable(Tx_pathname);
+
+ LOGI( AC_DisablePath, "%s/L%d: Rx_path_id = %d, Rx_pathname =%s, Tx_path_id = %d, Tx_pathname = %s",
+ __FUNCTION__, __LINE__, Rx_path_id, Rx_pathname, Tx_path_id, Tx_pathname);
+}
+
+/*
+Function: mute the path which is enabled and unmuted.
+path_para.d1: Rx_path_id
+path_para.d2: Tx_path_id
+path_para.d3: mute
+ */
+void AC_MutePath(AC_IPC_Package_Body *path_para) {
+ int Rx_path_id = path_para->d1;
+ int Tx_path_id = path_para->d2;
+ int mute = path_para->d3;
+
+ const char* Rx_pathname = ACM_GetPathName(Rx_path_id);
+ const char* Tx_pathname = ACM_GetPathName(Tx_path_id);
+
+ if ((NULL == Rx_pathname) || (NULL == Tx_pathname))
+ {
+ LOGE( AC_MutePath, "%s/L%d: RX or TX pathname is NULL.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ LOGI( AC_MutePath, "%s/L%d: Rx_path_id = %d, Rx_pathname =%s, Tx_path_id = %d, Tx_pathname = %s, mute =%d",
+ __FUNCTION__, __LINE__, Rx_path_id, Rx_pathname, Tx_path_id, Tx_pathname, mute);
+
+ if ((ACM_RC_OK_HIFI_MATCHED != APHAudioPathCheck (Rx_pathname, Tx_pathname))
+ && (ACM_RC_OK_VOICE_MATCHED != APHAudioPathCheck (Rx_pathname, Tx_pathname)))
+ {
+ LOGE( AC_MutePath, "%s/L%d: RX is not matched with TX.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ ACMAudioPathMute(Rx_pathname, mute);
+ ACMAudioPathMute(Tx_pathname, mute);
+}
+
+/*
+Function:set the volume for enabled path.
+path_para.d1: Rx_path_id
+path_para.d2: Tx_path_id
+path_para.d3: volume
+ */
+void AC_SetPathVolume(AC_IPC_Package_Body *path_para, AC_Digital_Gain *gain) {
+ int Rx_path_id = path_para->d1;
+ int Tx_path_id = path_para->d2;
+ unsigned int Volume = path_para->d3;
+
+ signed char input_gain = 0;
+ signed char input_gain_wb = 0;
+ signed char output_gain = 0;
+ signed char output_gain_wb = 0;
+ signed char rx_sidetone_gain = 0;
+ signed char rx_sidetone_gain_wb = 0;
+ signed char tx_sidetone_gain = 0;
+ signed char tx_sidetone_gain_wb = 0;
+ unsigned char vc_output_vol = Volume;
+ bool use_extra_vol = 0;
+
+ const char* Rx_pathname = ACM_GetPathName(Rx_path_id);
+ const char* Tx_pathname = ACM_GetPathName(Tx_path_id);
+
+ if ((NULL == Rx_pathname) || (NULL == Tx_pathname))
+ {
+ LOGE( AC_SetPathVolume, "%s/L%d: RX or TX pathname is NULL.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ LOGI( AC_SetPathVolume, "%s/L%d: Rx_path_id = %d, Rx_pathname =%s, Tx_path_id = %d, Tx_pathname = %s, Volume =%d",
+ __FUNCTION__, __LINE__, Rx_path_id, Rx_pathname, Tx_path_id, Tx_pathname, Volume);
+
+ if ((ACM_RC_OK_HIFI_MATCHED != APHAudioPathCheck (Rx_pathname, Tx_pathname))
+ && (ACM_RC_OK_VOICE_MATCHED != APHAudioPathCheck (Rx_pathname, Tx_pathname)))
+ {
+ LOGE( AC_SetPathVolume, "%s/L%d: RX is not matched with TX.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ ACMAudioPathVolumeSet(Rx_pathname, Volume);
+ ACMAudioPathVolumeSet(Tx_pathname, Volume);
+
+ //get the gain for voice
+ if (ACM_RC_OK_HIFI_MATCHED == APHAudioPathCheck (Rx_pathname, Tx_pathname))
+ {
+ LOGE( AC_SetPathVolume, "%s/L%d: RX is matched with TX about HIFI. Not need to get gain.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ get_msa_gain_by_path_name(Rx_pathname, Tx_pathname, 100, &input_gain, &input_gain_wb, &tx_sidetone_gain, &tx_sidetone_gain_wb, use_extra_vol);
+ get_msa_gain_by_path_name(Rx_pathname, Rx_pathname, vc_output_vol, &output_gain, &output_gain_wb, &rx_sidetone_gain, &rx_sidetone_gain_wb, use_extra_vol);
+
+ LOGI(AC_SetPathVolume, "%s/L%d: input_gain=0x%x, input_gain_wb=0x%x, output_gain=0x%x, output_gain_wb=0x%x.use_extra_vol=%d.\n",
+ __FUNCTION__, __LINE__, input_gain, input_gain_wb, output_gain, output_gain_wb, use_extra_vol);
+
+ gain->path_direction_Rx = VCM_PATH_OUT;
+ gain->digital_gain_Rx = output_gain | (output_gain_wb << 8);
+ gain->volume_Rx = vc_output_vol;
+
+ gain->path_direction_Tx = VCM_PATH_IN;
+ gain->digital_gain_Tx = input_gain | (input_gain_wb << 8);
+ gain->volume_Tx = vc_output_vol;
+
+ gain->path_direction_SideTone = VCM_PATH_SIDETONE;
+ gain->digital_gain_SideTone = rx_sidetone_gain | (rx_sidetone_gain_wb << 8);
+ gain->volume_SideTone = vc_output_vol;
+
+ LOGI(AC_SetPathVolume, "%s/L%d: digital_gain_Rx=0x%x, volume_Rx=%d, digital_gain_Tx=0x%x, volume_Tx=%d, digital_gain_SideTone=%d.\n",
+ __FUNCTION__, __LINE__, gain->digital_gain_Rx, gain->volume_Rx, gain->digital_gain_Tx, gain->volume_Tx, gain->digital_gain_SideTone);
+}
+
+/*
+Function: switch the path from enabled path list to another enabled path list.
+path_para.d1: Rx_path_id
+path_para.d2: Tx_path_id
+path_para.d3: Volume
+ */
+void AC_SwitchPath(AC_IPC_Package_Body *path_para, AC_Digital_Gain *gain) {
+ int Rx_path_id = path_para->d1;
+ int Tx_path_id = path_para->d2;
+ unsigned int Volume = path_para->d3;
+
+ signed char input_gain = 0;
+ signed char input_gain_wb = 0;
+ signed char output_gain = 0;
+ signed char output_gain_wb = 0;
+ signed char rx_sidetone_gain = 0;
+ signed char rx_sidetone_gain_wb = 0;
+ signed char tx_sidetone_gain = 0;
+ signed char tx_sidetone_gain_wb = 0;
+ unsigned char vc_output_vol = Volume;
+ bool use_extra_vol = 0;
+
+ //enable the pointed path
+ const char* Rx_pathname = ACM_GetPathName(Rx_path_id);
+ const char* Tx_pathname = ACM_GetPathName(Tx_path_id);
+
+ if ((NULL == Rx_pathname) || (NULL == Tx_pathname))
+ {
+ LOGE( AC_SwitchPath, "%s/L%d: RX or TX pathname is NULL.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ if ((ACM_RC_OK_HIFI_MATCHED != APHAudioPathCheck (Rx_pathname, Tx_pathname))
+ && (ACM_RC_OK_VOICE_MATCHED != APHAudioPathCheck (Rx_pathname, Tx_pathname)))
+ {
+ LOGE( AC_SwitchPath, "%s/L%d: RX is not matched with TX.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ LOGI( AC_SwitchPath, "%s/L%d: Rx_path_id = %d, Rx_pathname =%s, Tx_path_id = %d, Tx_pathname = %s, Volume =%d",
+ __FUNCTION__, __LINE__, Rx_path_id, Rx_pathname, Tx_path_id, Tx_pathname, Volume);
+
+ ACMAudioPathSwitch(Rx_pathname, Tx_pathname, Volume);
+
+ //get the gain for voice
+ if (ACM_RC_OK_HIFI_MATCHED == APHAudioPathCheck (Rx_pathname, Tx_pathname))
+ {
+ LOGE( AC_SwitchPath, "%s/L%d: RX is matched with TX about HIFI. Not need to get gain.",__FUNCTION__, __LINE__);
+ return;
+ }
+
+ get_msa_gain_by_path_name(Rx_pathname, Tx_pathname, 100, &input_gain, &input_gain_wb, &tx_sidetone_gain, &tx_sidetone_gain_wb, use_extra_vol);
+ get_msa_gain_by_path_name(Rx_pathname, Rx_pathname, vc_output_vol, &output_gain, &output_gain_wb, &rx_sidetone_gain, &rx_sidetone_gain_wb, use_extra_vol);
+
+ LOGI(AC_SwitchPath, "%s/L%d: input_gain = %d, input_gain_wb=%d, output_gain = %d, output_gain_wb=%d.use_extra_vol=%d.\n",
+ __FUNCTION__, __LINE__, input_gain, input_gain_wb, output_gain, output_gain_wb, use_extra_vol);
+
+ gain->path_direction_Rx = VCM_PATH_OUT;
+ gain->digital_gain_Rx = output_gain | (output_gain_wb << 8);
+ gain->volume_Rx = vc_output_vol;
+
+ gain->path_direction_Tx = VCM_PATH_IN;
+ gain->digital_gain_Tx = input_gain | (input_gain_wb << 8);
+ gain->volume_Tx = vc_output_vol;
+
+ gain->path_direction_SideTone = VCM_PATH_SIDETONE;
+ gain->digital_gain_SideTone = rx_sidetone_gain | (rx_sidetone_gain_wb << 8);
+ gain->volume_SideTone = vc_output_vol;
+
+ LOGI(AC_SwitchPath, "%s/L%d: digital_gain_Rx = %d, volume_Rx=%d, digital_gain_Tx = %d, volume_Tx=%d, digital_gain_SideTone=%d.\n",
+ __FUNCTION__, __LINE__, gain->digital_gain_Rx, gain->volume_Rx, gain->digital_gain_Tx, gain->volume_Tx, gain->digital_gain_SideTone);
+
+}
+
+#ifdef TARGET_mmp_asr1901_KSTR901
+extern void ACM_SendVEtoADSP(void);
+#endif
+
+//server to handle the message from client which is from CATSTUDIO tools ....
+static void ACM_Calibration_Socket_Server_Thread(void *data) {
+ (void)data;
+ unsigned int len;
+ struct sockaddr_un un;
+ AC_IPC_Package rcv_buf;
+
+ prctl(15,"ac_thread");
+ /* create a UNIX domain stream socket */
+ if ((fd_server = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0) {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "[Audio Calibration][%s][%d][create socket fail]\n", __FUNCTION__, __LINE__);
+ return;
+ }
+
+ unlink(ACM_CALIBRATION_SOCKET); /* in case it already exists */
+
+ /* fill in socket address structure */
+ memset(&un, 0, sizeof(un));
+ un.sun_family = AF_UNIX;
+ strcpy(un.sun_path, ACM_CALIBRATION_SOCKET);
+ len = offsetof(struct sockaddr_un, sun_path) + strlen(ACM_CALIBRATION_SOCKET);
+
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: addr=%s.\n", __FUNCTION__, __LINE__, un.sun_path);
+
+ /* bind the name to the descriptor */
+ if (bind(fd_server, (struct sockaddr *)&un, len) < 0) {
+
+ LOGE(ACM_Calibration_Socket_Server_Thread, "[Audio Calibration][%s][%d][bind fail][error %d (%s)]\n" \
+ , __FUNCTION__, __LINE__,errno, strerror(errno));
+ close(fd_server);
+ return;
+ }
+
+ if (chmod(ACM_CALIBRATION_SOCKET, 0666) < 0) {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "[Audio Calibration][%s][%d]FAIL to chmod ACM_CALIBRATION_SOCKET to 0666\n", __FUNCTION__, __LINE__);
+ close(fd_server);
+ return;
+ }
+ if (listen(fd_server, QLEN) < 0) { /* tell kernel we're a server */
+ LOGE(ACM_Calibration_Socket_Server_Thread, "[Audio Calibration][%s][%d][listen fail]\n", __FUNCTION__, __LINE__);
+ close(fd_server);
+ return;
+ }
+
+ while(1) {
+ len = sizeof(un);
+ //close last connection
+ if (clientfd_server >= 0) {
+ close(clientfd_server);
+ clientfd_server = -1;
+ //usleep(10000);
+ }
+
+ if ((clientfd_server = accept(fd_server, (struct sockaddr *)&un, &len)) < 0) {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "%s/L%d: Audio Calibration accept fail\n", __FUNCTION__, __LINE__);
+ continue;
+ }
+
+ if(read(clientfd_server, &rcv_buf, sizeof(rcv_buf))==-1) {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "%s/L%d: read fail\n", __FUNCTION__, __LINE__);
+ continue;
+ }
+
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: [receive type:0x%lx]-[d1:0x%lx][d2:0x%lx][d3:0x%lx][d4:0x%lx]\n",
+ __FUNCTION__, __LINE__,
+ rcv_buf.type, rcv_buf.body.d1, rcv_buf.body.d2, rcv_buf.body.d3, rcv_buf.body.d4);
+
+ switch (rcv_buf.type) {
+ case AUDIO_PHY_GetPathList:
+ {
+ PathsList paths_list;
+ int i = 0;
+ const ACMAPH_AudioPathID *path_config_table = NULL;
+
+ memset(&paths_list, 0x00, sizeof(paths_list));
+ path_config_table = ACM_GetPathConfigTable();
+
+ while (i < APH_PATH_ID_CNT)
+ {
+ strcpy(paths_list.path[paths_list.num++], (const char *)path_config_table[i].PathName);
+ i++;
+ }
+
+ if(write(clientfd_server, &paths_list, sizeof(paths_list)) == -1)
+ {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "%s/L%d: Get paths list failed", __FUNCTION__, __LINE__);
+ continue;
+ }
+
+ for(i = 0; i < paths_list.num; i++)
+ {
+ LOGI(ACM_Calibration_Socket_Server_Thread, " : %s\n", paths_list.path[i]);
+ }
+
+ break;
+ }
+
+ case AUDIO_PHY_GetPathStatus:
+ {
+ char tmp_buffer[PATHSTATUS_MAX] = {0};
+
+ if (ACMGetPathStatus(tmp_buffer, PATHSTATUS_MAX) != ACM_RC_OK)
+ {
+ sprintf(tmp_buffer, "-> Fail to get status!\n");
+ LOGE(ACM_Calibration_Socket_Server_Thread, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
+ continue;
+ }
+
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s.......", tmp_buffer);
+
+ if(write(clientfd_server, tmp_buffer, PATHSTATUS_MAX*sizeof(char)) == -1)
+ {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "%s/L%d: Get paths status failed", __FUNCTION__, __LINE__);
+ continue;
+ }
+
+ break;
+ }
+
+ case AUDIO_PHY_GetAudioMode:
+ {
+ audio_mode_t mode = AUDIO_MODE_INVALID;
+ int pcm_role = 0;
+ int pcm_rate = 0;
+
+ get_pcm_config(&pcm_role, &pcm_rate);
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s: modem_is_master=%s, modem_is_wb=%s.......", __FUNCTION__, pcm_role?"TRUE":"FALSE", pcm_rate?"WB":"NB");
+
+ mode = ACMGetAudioMode();
+
+ if ((mode != AUDIO_MODE_NORMAL) && (mode != AUDIO_MODE_IN_CALL))
+ {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "mode is not AUDIO_MODE_NORMAL and AUDIO_MODE_IN_CALL");
+ continue;
+ }
+
+ LOGI(ACM_Calibration_Socket_Server_Thread, "mode = %s.......",
+ (mode == AUDIO_MODE_NORMAL) ? "AUDIO_MODE_NORMAL" : "AUDIO_MODE_IN_CALL");
+
+ if(write(clientfd_server, &mode, sizeof(audio_mode_t)) == -1)
+ {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "%s/L%d: Get mode failed", __FUNCTION__, __LINE__);
+ continue;
+ }
+
+ break;
+ }
+ case AUDIO_PHY_ReloadCalibrationData:
+ {
+ AC_Digital_Gain gain;
+
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: ReloadCalibrationData", __FUNCTION__, __LINE__);
+ memset(&gain, 0x00, sizeof(AC_Digital_Gain));
+
+ AC_ReloadCalibrationData(&gain);
+
+ if(write(clientfd_server, &gain, sizeof(AC_Digital_Gain)) == -1) {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "%s/L%d: Audio Calibration failed", __FUNCTION__, __LINE__);
+ continue;
+ }
+ }
+
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: ReloadCalibrationData", __FUNCTION__, __LINE__);
+ break;
+
+ case AUDIO_PHY_SetPathVolume:
+ {
+ AC_Digital_Gain gain;
+
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: SetPathVolume", __FUNCTION__, __LINE__);
+ memset(&gain, 0x00, sizeof(AC_Digital_Gain));
+ AC_SetPathVolume(&rcv_buf.body, &gain);
+
+ if(write(clientfd_server, &gain, sizeof(AC_Digital_Gain)) == -1) {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "%s/L%d: Audio Calibration failed", __FUNCTION__, __LINE__);
+ continue;
+ }
+ }
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: SetPathVolume", __FUNCTION__, __LINE__);
+ break;
+
+ case AUDIO_PHY_EnablePath:
+ {
+ AC_Digital_Gain gain;
+
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: EnablePath", __FUNCTION__, __LINE__);
+ memset(&gain, 0x00, sizeof(AC_Digital_Gain));
+ AC_EnablePath(&rcv_buf.body, &gain);
+
+ if(write(clientfd_server, &gain, sizeof(AC_Digital_Gain)) == -1) {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "%s/L%d: Audio Calibration failed", __FUNCTION__, __LINE__);
+ continue;
+ }
+ }
+
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: EnablePath", __FUNCTION__, __LINE__);
+ break;
+
+ case AUDIO_PHY_DisablePath:
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: DisablePath", __FUNCTION__, __LINE__);
+ AC_DisablePath(&rcv_buf.body);
+ break;
+
+ case AUDIO_PHY_MutePath:
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: MutePath", __FUNCTION__, __LINE__);
+ AC_MutePath(&rcv_buf.body);
+ break;
+
+ case AUDIO_PHY_SwitchPath:
+ {
+ AC_Digital_Gain gain;
+
+ memset(&gain, 0x00, sizeof(AC_Digital_Gain));
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: SwitchPath", __FUNCTION__, __LINE__);
+ AC_SwitchPath(&rcv_buf.body, &gain);
+
+ if(write(clientfd_server, &gain, sizeof(AC_Digital_Gain)) == -1) {
+ LOGE(ACM_Calibration_Socket_Server_Thread, "%s/L%d: Audio Calibration failed", __FUNCTION__, __LINE__);
+ continue;
+ }
+ }
+
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: SwitchPath", __FUNCTION__, __LINE__);
+ break;
+
+#ifdef TARGET_mmp_asr1901_KSTR901
+ case AUDIO_PHY_SendVEtoADSP:
+ LOGI(ACM_Calibration_Socket_Server_Thread, "%s/L%d: SendVEtoADSP", __FUNCTION__, __LINE__);
+ ACM_SendVEtoADSP();
+ break;
+#endif
+
+ default:
+ continue;
+ }
+ }
+
+ unlink(ACM_CALIBRATION_SOCKET);
+ return;
+}
+
+
+void ACM_Init_Calibration_IPC(void)
+{
+ pthread_create( &ACM_Calibration_Server, NULL, (void *)ACM_Calibration_Socket_Server_Thread, NULL);
+}
+
+void ACM_Cancel_Calibration_IPC(void)
+{
+ pthread_cancel(ACM_Calibration_Server);
+
+ if (pthread_join(ACM_Calibration_Server, NULL)) {
+ LOGE(ACM_Cancel_Calibration_IPC, "%s/L%d: fail to pthread_join() ACM_Calibration_Server", __FUNCTION__, __LINE__);
+ }
+
+ if (fd_server >= 0) {
+ close(fd_server);
+ fd_server = -1;
+ LOGE(ACM_Cancel_Calibration_IPC, "%s/L%d: close fd_server.", __FUNCTION__, __LINE__);
+ }
+
+ if (clientfd_server >= 0) {
+ close(clientfd_server);
+ clientfd_server = -1;
+ LOGE(ACM_Cancel_Calibration_IPC, "%s/L%d: close clientfd_server.", __FUNCTION__, __LINE__);
+ }
+
+ return;
+}