blob: 23737bf8d8af03b1d8d7233eefcd2dadabacb5e8 [file] [log] [blame]
/*
* 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;
}