blob: a947a7488d2d1bf558dc312a868ef4fb813d2bbd [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.
*
*/
#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(&param);
}
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(&param);
//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(&param);
}
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(&param);
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);
}