| /* |
| * 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; |
| } |