commit c650b45892aa8be87f3e88ee6eae5df053a0a047 Author: PaulK Date: Sun May 15 11:53:58 2011 +0200 Added a replacement for libhtc_acoustic.so's set_acoustic_parameters(), which is required to make in-call volume adjustment and No Mic Wired Headset work (and probably other things related to audio). This function loads values from /system/etc/AudioPara4.csv to MSM shared memory. Created: libaudio/AudioAcoustic.cpp, libaudio/AudioAcoustic.h Modified: libaudio/Android.mk, libaudio/AudioHardware.cpp diff --git a/libaudio/Android.mk b/libaudio/Android.mk index 5f28582..7fd0b35 100644 --- a/libaudio/Android.mk +++ b/libaudio/Android.mk @@ -43,6 +43,7 @@ LOCAL_SHARED_LIBRARIES += libdl endif LOCAL_SRC_FILES += AudioHardware.cpp +LOCAL_SRC_FILES += AudioAcoustic.cpp LOCAL_CFLAGS += -fno-short-enums diff --git a/libaudio/AudioAcoustic.cpp b/libaudio/AudioAcoustic.cpp new file mode 100644 index 0000000..fc6b179 --- /dev/null +++ b/libaudio/AudioAcoustic.cpp @@ -0,0 +1,643 @@ +/* +** Copyright 2011, Paul Kocialkowski +** Deeply based on: git://gitorious.org/~jbruneaux/xdandroid/hardware_msm7k_libacoustic.git (froyo branch) +** for functions openacousticfd, ParseAudioParaLine, ReadAudioParaFromFile, htc_acoustic_deinit and msm72xx_set_acoustic_done +** Credit: Jbruneaux +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#define LOG_TAG "AudioAcousticMSM72XX" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include "AudioAcoustic.h" + +#define AUDIO_PARA_CUSTOM_FILENAME "/sdcard/AudioPara4.csv" +#define AUDIO_PARA_DEFAULT_FILENAME "/system/etc/AudioPara4.csv" + +namespace android { + +struct au_table_s { + union { + struct au_table_st table; + char array[0x80]; + }; +}; + +struct be_table_s { + union { + struct be_table_st table; + uint16_t array[0x80]; + }; +}; + +struct d_table_s { + union { + struct d_table_st table; + uint16_t array[0xA]; // Size = 0x8 on some devices like diamond. + }; +}; + +struct fg_table_s { + union { + struct fg_table_st table; // Array size is 0x140 + uint16_t array[0xA0]; + }; +}; + +/* This struct is not used */ +struct c_table_s { + union { + struct fg_table_st table; + uint16_t array[0x50]; + }; +}; + + +/* These bits are required to make it work, although their meaning is not clear (these are not on the CSV file). + It's probably some kind of end-delimiter. */ +uint8_t htc_acoustic_end[] = { 0x78, 0x56, 0x34, 0x12 }; + +/*********************************************************************************** + * + * Global variables + * + ***********************************************************************************/ +/* Tables containing data parsed from CSV file */ +static struct au_table_s* Audio_Path_Table = NULL; /* a_table ('A') */ +static uint8_t APT_max_index = 0; +static struct au_table_s* Audio_Path_Uplink_Table = NULL; /* u_table ('U') */ +static uint8_t APUT_max_index = 0; +static struct fg_table_s* Phone_Acoustic_Table = NULL; /* f_table ('F' + 'B') */ +static uint8_t PAT_max_index = 0; +static struct fg_table_s* BT_Phone_Acoustic_Table = NULL; /* g_table ('E' + 'G') */ +static uint8_t BTPAT_max_index = 0; +static struct d_table_s* HTC_VOC_CAL_CODEC_TABLE_Table = NULL; /* d_table ('D') */ +static uint8_t HVCCT_max_index = 0; +/* These are not used */ +static struct c_table_s* CE_Acoustic_Table = NULL; /* c_table ('C') */ +static uint8_t CEAT_max_index = 0; + +/* table-specific adresses for mmap and size */ +static int mmap_size = 0xd000; +static int mmap_address_audio_path_table = 0x0; +static int mmap_address_audio_path_uplink_table = 0xc00; +static int mmap_address_phone_acoustic_table = 0x1800; +static int mmap_address_bt_phone_acoustic_table = 0x4a00; +static int mmap_address_htc_voc_cal_codec_table_table = 0xc700; +static int mmap_address_htc_acoustic_end = 0xc8e0; + +int acousticfd = 0; + +/* Open the acoustic (/dev/htc-acoustic) file descriptor */ +int openacousticfd(void) +{ + acousticfd = open("/dev/htc-acoustic", O_RDWR | O_SYNC); + if ( acousticfd < 0 ) { + LOGE("Error opening dev %s (fd = %d). Error %s (%d)", "/dev/htc-acoustic", acousticfd, + strerror(errno), errno); + return -1; + } + return 0; +} + +/* mmap /dev/htc-acoustic to write the tables in a part of MSM shared memory */ +int htc_acoustic_mmap(void) +{ + uint16_t table16_t=0; + uint8_t *table8_t=NULL; + + uint8_t *mmap_p=NULL; + uint8_t *mmap_base_p=NULL; + + int i, j, k, l=0; + + mmap_p = (uint8_t *) + mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, acousticfd, 0); + if(mmap_p == MAP_FAILED) + { + LOGE("mmap failed.\n"); + return -1; + } + + mmap_base_p=mmap_p; + + LOGV("mmap base is at 0x%p\n", mmap_base_p); + + /* Fill memory with 0 */ + memset(mmap_p, 0, mmap_size); + + /* + * What we do here (for each table): + * - set mmap_p to the address where the table has to be loaded (mmap base address + table-specific address) + * - convert all the data in the table to many uint8_t so these can be easilly written using *mmap_p=value; + * - write data in memory (*mmap_p=value;) and increment mmap_p as needed. + */ + + mmap_p=mmap_base_p + mmap_address_audio_path_table; + + /* Copy Audio_Path_Table to MSM shared memory */ + for(i=0 ; i < APT_max_index ; i++) + for(j=0 ; j < sizeof(Audio_Path_Table[i]) / sizeof(Audio_Path_Table[i].array[j]) ; j++) + { + table16_t=Audio_Path_Table[i].array[j]; + table8_t=(uint8_t *) &table16_t; + + l=sizeof(Audio_Path_Table[i].array[j]) / sizeof(uint8_t); + + for(k=0 ; k < l ; k++) + { + *mmap_p=*(table8_t+k); + mmap_p++; + } + } + + mmap_p=mmap_base_p + mmap_address_audio_path_uplink_table; + + /* Copy Audio_Path_Uplink_Table to MSM shared memory */ + for(i=0 ; i < APUT_max_index ; i++) + for(j=0 ; j < sizeof(Audio_Path_Uplink_Table[i]) / sizeof(Audio_Path_Uplink_Table[i].array[j]) ; j++) + { + table16_t=Audio_Path_Uplink_Table[i].array[j]; + table8_t=(uint8_t *) &table16_t; + + l=sizeof(Audio_Path_Uplink_Table[i].array[j]) / sizeof(uint8_t); + + for(k=0 ; k < l ; k++) + { + *mmap_p=*(table8_t+k); + mmap_p++; + } + } + + mmap_p=mmap_base_p + mmap_address_phone_acoustic_table; + + /* Copy Phone_Acoustic_Table to MSM shared memory */ + for(i=0 ; i < PAT_max_index ; i++) + for(j=0 ; j < sizeof(Phone_Acoustic_Table[i]) / sizeof(Phone_Acoustic_Table[i].array[j]) ; j++) + { + table16_t=Phone_Acoustic_Table[i].array[j]; + table8_t=(uint8_t *) &table16_t; + + l=sizeof(Phone_Acoustic_Table[i].array[j]) / sizeof(uint8_t); + + for(k=0 ; k < l ; k++) + { + *mmap_p=*(table8_t+k); + mmap_p++; + } + } + + mmap_p=mmap_base_p + mmap_address_bt_phone_acoustic_table; + + /* Copy BT_Phone_Acoustic_Table to MSM shared memory */ + for(i=0 ; i < BTPAT_max_index ; i++) + for(j=0 ; j < sizeof(BT_Phone_Acoustic_Table[i]) / sizeof(BT_Phone_Acoustic_Table[i].array[j]) ; j++) + { + table16_t=BT_Phone_Acoustic_Table[i].array[j]; + table8_t=(uint8_t *) &table16_t; + + l=sizeof(BT_Phone_Acoustic_Table[i].array[j]) / sizeof(uint8_t); + + for(k=0 ; k < l ; k++) + { + *mmap_p=*(table8_t+k); + mmap_p++; + } + } + + mmap_p=mmap_base_p + mmap_address_htc_voc_cal_codec_table_table; + + /* Copy HTC_VOC_CAL_CODEC_TABLE_Table to MSM shared memory */ + for(i=0 ; i < HVCCT_max_index ; i++) + for(j=0 ; j < sizeof(HTC_VOC_CAL_CODEC_TABLE_Table[i]) / sizeof(HTC_VOC_CAL_CODEC_TABLE_Table[i].array[j]) ; j++) + { + table16_t=HTC_VOC_CAL_CODEC_TABLE_Table[i].array[j]; + table8_t=(uint8_t *) &table16_t; + + l=sizeof(HTC_VOC_CAL_CODEC_TABLE_Table[i].array[j]) / sizeof(uint8_t); + + for(k=0 ; k < l ; k++) + { + *mmap_p=*(table8_t+k); + mmap_p++; + } + } + + mmap_p=mmap_base_p + mmap_address_htc_acoustic_end; + + /* Copy htc_acoustic_end to MSM shared memory */ + for(i=0 ; i < sizeof(htc_acoustic_end) ; i++) + { + table16_t=htc_acoustic_end[i]; + table8_t=(uint8_t *) &table16_t; + + l=sizeof(htc_acoustic_end[i]) / sizeof(uint8_t); + + for(k=0 ; k < l ; k++) + { + *mmap_p=*(table8_t+k); + mmap_p++; + } + } + +#if 0 + /* This is to dump the memory in /data/dump_data (you need to create the file first) */ + mmap_p=mmap_base_p; + + int dumpfd; + int len; + + dumpfd=open("/data/dump_data", O_TRUNC | O_RDWR); + if(dumpfd < 0) + LOGE("dumpfd failed\n"); + else + { + for (len = 0; len < 0xd000; len++) + { + if( write(dumpfd, mmap_p, sizeof(uint8_t) ) < 0) + { + LOGE("write failed"); + break; + } + mmap_p++; + } + close(dumpfd); + } +#endif + + munmap(mmap_p, 0xd000); + + return 0; +} + +/* Parse a CSV line and store the values in the tables */ +int ParseAudioParaLine(char* line, int len) +{ + char *token, *ps; + int table_num; + int field_count = 0; + + /* Parse the first field */ + token = strtok(line, ","); + + if(strcmp("Header", token) == 0) + { + token = strtok(NULL, ","); + LOGD("CSV Header: %s\n", token); + return 0; + } + + switch ( token[0] ) { + case 'A': + table_num = strtol(token + 1, &ps, 10); + if ( table_num > 31) { + return -EINVAL; + } + if ( APT_max_index < (table_num+1) ) APT_max_index = table_num+1; + // LOGV("Audio Path Table: %d\n", table_num); + /* Skip the mode name string field */ + strtok(NULL, ","); + while ( (token = strtok(NULL, ",")) ) { + Audio_Path_Table[table_num].array[field_count++] = strtol(token, &ps, 16); + }; + break; + + case 'B': + case 'F': + table_num = strtol(token + 1, &ps, 10); + if ( table_num > 99) { + return -EINVAL; + } + if ( PAT_max_index < (table_num+1) ) PAT_max_index = table_num+1; + // LOGV("Phone Acoustic Table: %d\n", table_num); + /* Skip the mode name string field */ + strtok(NULL, ","); + while ( (token = strtok(NULL, ",")) ) { + Phone_Acoustic_Table[table_num].array[field_count++] = strtol(token, &ps, 16); + }; + break; + + case 'C': + table_num = strtol(token + 1, &ps, 10); + if ( table_num > 14) { + return -EINVAL; + } + if ( CEAT_max_index < (table_num+1) ) CEAT_max_index = table_num+1; + // LOGV("CE Acoustic Table: %d\n", table_num); + /* Skip the mode name string field */ + strtok(NULL, ","); + while ( (token = strtok(NULL, ",")) ) { + CE_Acoustic_Table[table_num].array[field_count++] = strtol(token, &ps, 16); + }; + break; + + case 'D': + table_num = strtol(token + 1, &ps, 10); + if ( table_num > 31) { + return -EINVAL; + } + if ( HVCCT_max_index < (table_num+1) ) HVCCT_max_index = table_num+1; + // LOGV("HTC_VOC_CAL_CODEC_TABLE Table: %d\n", table_num); + /* Skip the mode name string field */ + strtok(NULL, ","); + while ( (token = strtok(NULL, ",")) ) { + HTC_VOC_CAL_CODEC_TABLE_Table[table_num].array[field_count++] = strtol(token, &ps, 16); + }; + break; + + case 'E': + case 'G': + table_num = strtol(token + 1, &ps, 10); + if ( table_num > 100) { + return -EINVAL; + } + if ( BTPAT_max_index < (table_num+1) ) BTPAT_max_index = table_num+1; + // LOGV("BT Phone Acoustic Table: %d\n", table_num); + /* Skip the mode name string field */ + strtok(NULL, ","); + while ( (token = strtok(NULL, ",")) ) { + BT_Phone_Acoustic_Table[table_num].array[field_count++] = strtol(token, &ps, 16); + }; + break; + + case 'H': + // LOGV("It's just a header line, skip it\n"); + return 0; + + case 'U': + table_num = strtol(token + 1, &ps, 10); + if ( table_num > 31) { + return -EINVAL; + } + if ( APUT_max_index < (table_num+1) ) APUT_max_index = table_num+1; + // LOGV("Audio Path Table Uplink: %d\n", table_num); + /* Skip the mode name string field */ + strtok(NULL, ","); + while ( (token = strtok(NULL, ",")) ) { + Audio_Path_Uplink_Table[table_num].array[field_count++] = strtol(token, &ps, 16); + }; + break; + + default: + printf("Unknown parameter field %c\n", token[0]); + return -1; + } + + return 0; +} + +/* Open the CSV file, malloc the tables and send each line to ParseAudioParaLine */ +int ReadAudioParaFromFile(void) +{ + struct stat st; + char *read_buf=NULL; + char *next_str = NULL; + char *current_str = NULL; + int csvfd; + int len; + + static const char *path = + AUDIO_PARA_CUSTOM_FILENAME; + + csvfd = open(path, O_RDONLY); + if (csvfd < 0) { + /* Failed to open custom parameters file, fallback to the default file ... */ + LOGE("Failed to open %s. Error %s (%d)\n", + path, strerror(errno), errno); + + LOGD("Trying with default file"); + path = AUDIO_PARA_DEFAULT_FILENAME; + csvfd = open(path, O_RDONLY); + if (csvfd < 0) { + LOGE("Failed to open %s. Error %s (%d)\n", + path, strerror(errno), errno); + return -1; + } + } + + LOGD("Successfully opened %s\n", path); + + if (fstat(csvfd, &st) < 0) { + printf("Failed to stat %s: %s (%d)\n", + path, strerror(errno), errno); + close(csvfd); + return -1; + } + +#if 0 + /* malloc is used instead of mmap */ + read_buf = (char *) mmap(0, st.st_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE, + csvfd, 0); +#endif + + read_buf=(char *) malloc(st.st_size * sizeof(char)); + read(csvfd, read_buf, st.st_size * sizeof(char)); + current_str = read_buf; + + if (!read_buf) { + LOGE("Failed to malloc parameters file: %s (%d)\n", + strerror(errno), errno); + close(csvfd); + return -1; + } + + if ( Audio_Path_Table == NULL ) { + Audio_Path_Table = (struct au_table_s*) malloc(32 * sizeof(struct au_table_s) ); // 0x1000 + if (Audio_Path_Table == NULL) { + LOGE("Failed to malloc Audio_Path_Table\n"); + return -1; + } + } + + if ( Audio_Path_Uplink_Table == NULL ) { + Audio_Path_Uplink_Table = (struct au_table_s*) malloc(32 * sizeof(struct au_table_s) ); // 0x1000 + if (Audio_Path_Uplink_Table == NULL) { + LOGE("Failed to malloc Audio_Path_Uplink_Table\n"); + return -1; + } + } + + if ( Phone_Acoustic_Table == NULL ) { + Phone_Acoustic_Table = (struct fg_table_s*) malloc(100 * sizeof(struct fg_table_s) ); // 0x3C00 + if (Phone_Acoustic_Table == NULL) { + LOGE("Failed to malloc Phone_Acoustic_Table\n"); + return -1; + } + } + + if ( BT_Phone_Acoustic_Table == NULL ) { + BT_Phone_Acoustic_Table = (struct fg_table_s*) malloc(100 * sizeof(struct fg_table_s) ); // 0x7800 + if (BT_Phone_Acoustic_Table == NULL) { + LOGE("Failed to malloc BT_Phone_Acoustic_Table\n"); + return -1; + } + } + + if ( HTC_VOC_CAL_CODEC_TABLE_Table == NULL ) { + HTC_VOC_CAL_CODEC_TABLE_Table = (struct d_table_s*) malloc(32 * sizeof(struct d_table_s)); + if (HTC_VOC_CAL_CODEC_TABLE_Table == NULL) { + LOGE("Failed to malloc HTC_VOC_CAL_CODEC_TABLE_Table\n"); + return -1; + } + } + + if ( CE_Acoustic_Table == NULL ) { + CE_Acoustic_Table = (struct c_table_s*) malloc(15 * sizeof(struct c_table_s) ); // 0x960 + if (CE_Acoustic_Table == NULL) { + LOGE("Failed to malloc CE_Acoustic_Table\n"); + return -1; + } + } + + current_str = read_buf; + while (1) { + len=0; + next_str = strchr(current_str, '\n'); + + if (next_str == NULL) + { + break; + } + + len = next_str - current_str; + *next_str++ = '\0'; + /* Call the function to parse the CSV line */ + if ( ParseAudioParaLine(current_str, len) < 0 ) { + LOGE("ParseAudioParaLine failed :(\n"); + break; + } + current_str = next_str; + } + + /* free is used instead of munmap */ +// munmap(read_buf, st.st_size); + free(read_buf); + close(csvfd); + + LOGD("Read:\n"); + LOGD("%d Audio_Path_Table entries\n", APT_max_index); + LOGD("%d Audio_Path_Uplink_Table entries\n", APUT_max_index); + LOGD("%d Phone_Acoustic_Table entries\n", PAT_max_index); + LOGD("%d BT_Phone_Acoustic_Table entries\n", BTPAT_max_index); + LOGD("%d HTC_VOC_CAL_CODEC_TABLE_Table entries\n", HVCCT_max_index); + LOGD("%d CE_Acoustic_Table entries\n", CEAT_max_index); + + return 0; +} + +/* Free memory, fd, etc */ +int htc_acoustic_deinit(void) +{ + int rc = 0; + + /* Close the acoustic driver */ + close(acousticfd); + + /* Free the memory */ + if ( Audio_Path_Table != NULL ) + free(Audio_Path_Table); + if ( Audio_Path_Uplink_Table != NULL ) + free(Audio_Path_Uplink_Table); + if ( Phone_Acoustic_Table != NULL ) + free(Phone_Acoustic_Table); + if ( BT_Phone_Acoustic_Table != NULL ) + free(BT_Phone_Acoustic_Table); + if ( HTC_VOC_CAL_CODEC_TABLE_Table != NULL ) + free(HTC_VOC_CAL_CODEC_TABLE_Table); + + return rc; +} + +/* Tell /dev/htc-acoustic that we've written all the tables */ +int msm72xx_set_acoustic_done(void) +{ + LOGV("msm72xx_set_acoustic_done"); + + if (ioctl(acousticfd, ACOUSTIC_ARM11_DONE, NULL) < 0) { + LOGE("ACOUSTIC_ARM11_DONE error."); + return -EIO; + } + return 0; +} + +/* Main function, called by AudioHardware.cpp */ +int set_acoustic_parameters(void) +{ + LOGV("set_acoustic_parameters called\n"); + + /* Open the acoustic (/dev/htc-acoustic) file descriptor */ + if(openacousticfd() < 0) + { + LOGE("openacousticfd failed\n"); + return -1; + } + + //set_device_configuration to set the memory adresses of the tables + + /* Open and parse the CSV file then store the values in tables */ + if(ReadAudioParaFromFile() < 0) + { + LOGE("ReadAudioParaFromFile failed\n"); + return -1; + } + + /* mmap /dev/htc-acoustic to write the tables in a part of MSM shared memory */ + if(htc_acoustic_mmap() < 0) + { + LOGE("htc_acoustic_mmap failed\n"); + return -1; + } + + /* Tell /dev/htc-acoustic that we've written all the tables */ + if(msm72xx_set_acoustic_done() < 0) + { + LOGE("msm72xx_set_acoustic_done failed\n"); + return -1; + } + + /* Free memory, fd, etc */ + htc_acoustic_deinit(); + + return 0; +} + +}; // namespace android diff --git a/libaudio/AudioAcoustic.h b/libaudio/AudioAcoustic.h new file mode 100644 index 0000000..4743728 --- /dev/null +++ b/libaudio/AudioAcoustic.h @@ -0,0 +1,211 @@ +/* +** Copyright 2011, Paul Kocialkowski +** Based on: https://gitorious.org/~jbruneaux/xdandroid/hardware_msm7k_libacoustic +** Credit: Jbruneaux +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef ANDROID_AUDIO_ACOUSTIC_H +#define ANDROID_AUDIO_ACOUSTIC_H + +#define MAX_MODE_NAME_LENGTH 32 + +namespace android { + +int openacousticfd(void); +int htc_acoustic_mmap(void); +int ParseAudioParaLine(char* line, int len); +int ReadAudioParaFromFile(void); +int htc_acoustic_deinit(void); +int msm72xx_set_acoustic_done(void); +int set_acoustic_parameters(void); + +/* Acoustic IOCTLs */ +#define ACOUSTIC_IOCTL_MAGIC 'p' +#define ACOUSTIC_ARM11_DONE _IOW(ACOUSTIC_IOCTL_MAGIC, 22, unsigned int) + +/* CSV lines desc */ +struct header_s { + uint8_t Header; + char Mode[MAX_MODE_NAME_LENGTH]; +}; + +struct register_table_s { + uint8_t Address; + uint8_t Reg; +}; + +struct fg_table_st { +// char name[MAX_MODE_NAME_LENGTH]; + uint16_t volume_level; + uint16_t codecTxGain; + uint16_t codecRxGain; + uint16_t codecSTGain; + uint16_t txVolume; + uint16_t rxVolume; + uint16_t rxAgcEnableFlag; + uint16_t compFlinkStaticGain; + uint16_t compFlinkAIGFlag; + uint16_t expFlinkThreshold; + uint16_t expFlinkSlope; + uint16_t compFlinkThreshold; + uint16_t compFlinkSlope; + uint16_t comFlinkRmsTav; + uint16_t compFlinkReleaseK; + uint16_t compFlinkAIGMin; + uint16_t compFlinkAIGMax; + uint16_t rxAvcEnableFlag; + uint16_t avcRlinkSensitivityOffset; + uint16_t avcFlinkHeadroom; + uint16_t txAgcEnableFlag; + uint16_t compRlinkStaticGain; + uint16_t compRlinkAIGFlag; + uint16_t expRlinkThreshold; + uint16_t expRlinkSlope; + uint16_t compRlinkThreshold; + uint16_t compRlinkSlope; + uint16_t comRlinkRmsTav; + uint16_t compRlinkReleaseK; + uint16_t compRlinkAIGMin; + uint16_t compRlinkAIGMax; + uint16_t NLPP_limit; + uint16_t NLPP_gain; + uint16_t AF_limit; + uint16_t HS_mode; + uint16_t Tuning_mode; + uint16_t echo_path_delay; + uint16_t OutputGain; + uint16_t InputGain; + uint16_t AF_twoalpha; + uint16_t AF_erl; + uint16_t AF_taps; + uint16_t AF_present_coefs; + uint16_t AF_offset; + uint16_t AF_erl_bg; + uint16_t AF_taps_bg; + uint16_t PCD_threshold; + uint16_t minimum_erl; + uint16_t erl_step; + uint16_t max_noise_floor; + uint16_t Det_threshold; + uint16_t SPDET_Far; + uint16_t SPDET_mic; + uint16_t SPDET_xclip; + uint16_t DENS_tail_alpha; + uint16_t DENS_tail_portion; + uint16_t DENS_gamma_e_alpha; + uint16_t DENS_gamma_e_dt; + uint16_t DENS_gamma_e_low; + uint16_t DENS_gamma_e_rescue; + uint16_t DENS_gamma_e_high; + uint16_t DENS_spdet_near; + uint16_t DENS_spdet_act; + uint16_t DENS_gamma_n; + uint16_t DENS_NFE_blocksize; + uint16_t DENS_limit_NS; + uint16_t DENS_NL_atten; + uint16_t DENS_CNI_Level; + uint16_t WB_echo_ratio; + uint16_t rxPcmFiltEnableFlag; + uint16_t rxPcmFiltCoeff[7]; + uint16_t txPcmFiltEnableFlag; + uint16_t txPcmFiltCoeff[7]; + uint16_t rxiirFiltNumCoeff[18]; + uint16_t rxiirFiltDenCoeff[12]; + uint16_t rxiirFiltNumShiftFactor[4]; + uint16_t txiirFiltNumCoeff[18]; + uint16_t txiirFiltDenCoeff[12]; + uint16_t txiirFiltNumShiftFactor[4]; + uint16_t ecparameterupdated; +}; + +struct d_table_st { + uint16_t routing_mode_config; + uint16_t internal_codec_config; + uint16_t external_codec_config; + uint16_t pcm_ctrl; + uint16_t codec_intf_ctrl; + uint16_t dma_path_ctrl; + uint16_t eight_khz_int_mode; + uint16_t rx_codec_stereo_config; + uint16_t tx_codec_stereo_config; + uint16_t ECNS; +// uint16_t unk0; +}; + +struct be_table_st { + uint16_t Operator_ID; + uint16_t Vocpath; + uint16_t volume_level; + uint16_t codecTxGain; + uint16_t codecRxGain; + uint16_t codecSTGain; + uint16_t txVolume; + uint16_t rxVolume; + uint16_t pcmFormatCtrl; + uint16_t ecSwitch; + uint16_t ecMode; + uint16_t ecStartupMuteHangoverThres; + uint16_t ecFarendHangoverThres; + uint16_t esecDoubletalkHangoverThres; + uint16_t hecDoubletalkHangoverThres; + uint16_t aecDoubletalkHangoverThres; + uint16_t ecStartupMuteMode; + uint16_t ecMuteOverride; + uint16_t ecStartupErleThres; + uint16_t ecForceHalfDuplex; + uint16_t esecResetThres; + uint16_t hecResetThres; + uint16_t aecResetThres; + uint16_t ecInputSampOffset; + uint16_t rxAgcEnableFlag; + uint16_t compFlinkStaticGain; + uint16_t compFlinkAIGFlag; + uint16_t expFlinkThreshold; + uint16_t expFlinkSlope; + uint16_t compFlinkThreshold; + uint16_t compFlinkSlope; + uint16_t rxAvcEnableFlag; + uint16_t avcRlinkSensitivityOffset; + uint16_t avcFlinkHeadroom; + uint16_t txAgcEnableFlag; + uint16_t compRlinkStaticGain; + uint16_t compRlinkAIGFlag; + uint16_t expRlinkThreshold; + uint16_t expRlinkSlope; + uint16_t compRlinkThreshold; + uint16_t compRlinkSlope; + uint16_t nsSwitch; + uint16_t nsMinGain; + uint16_t nsSlope; + uint16_t nsSNRThreshold; + uint16_t rxPcmFiltCoeff[6]; + uint16_t txPcmFiltCoeff[6]; + uint16_t ec_reset_flag; + uint16_t Reserved[5]; + uint16_t MCC_Val; + uint16_t MNC_Val; +}; + +struct au_table_st { + struct register_table_s register_table[26]; /* Add 1 .. Add 26 */ + uint8_t Total_number; + uint8_t Delay_number; + uint8_t Delay_time; + uint8_t extra[12]; +}; + +}; // namespace android + +#endif // ANDROID_AUDIO_ACOUSTIC_H diff --git a/libaudio/AudioHardware.cpp b/libaudio/AudioHardware.cpp index d71e131..4ac6672 100644 --- a/libaudio/AudioHardware.cpp +++ b/libaudio/AudioHardware.cpp @@ -32,6 +32,8 @@ // hardware specific functions #include "AudioHardware.h" +#include "AudioAcoustic.h" + #include #define LOG_SND_RPC 0 // Set to 1 to log sound RPC's @@ -46,14 +48,67 @@ const uint32_t AudioHardware::inputSamplingRates[] = { static int snd_get_endpoint(int cnt,msm_snd_endpoint * ept){ int fd; int status; - fd = open("/dev/msm_snd",O_RDWR); - if (fd < 0) { - LOGE("Cannot open msm_snd device"); - close(fd); - return -1; + + /* note that index != id: + cnt is index, which is < snd_get_num(); + ept->id is index before ioctl, + and will be filled with the correct id by the kernel-side driver */ + + switch(cnt) + { + /* Set endpoints we don't get with ioctl. + Kernel-provided indexes are up to 38, + so we use fictive indexes > 38 here */ + case 39: + strcpy(ept->name, "CARKIT"); + ept->id=4; + status=1; + break; + case 40: + strcpy(ept->name, "TTY_FULL"); + ept->id=5; + status=1; + break; + case 41: + strcpy(ept->name, "TTY_VCO"); + ept->id=6; + status=1; + break; + case 42: + strcpy(ept->name, "TTY_HCO"); + ept->id=7; + status=1; + break; + case 43: + strcpy(ept->name, "NO_MIC_HEADSET"); + ept->id=8; + status=1; + break; + case 44: + strcpy(ept->name, "FM_HEADSET"); + ept->id=9; + status=1; + break; + case 45: + strcpy(ept->name, "FM_SPEAKER"); + ept->id=11; + status=1; + break; + + /* Otherwise, get the endpoint with ioctl */ + default: + + fd = open("/dev/msm_snd",O_RDWR); + if (fd < 0) { + LOGE("Cannot open msm_snd device"); + close(fd); + return -1; + } + status = ioctl(fd,SND_GET_ENDPOINT, ept); + close(fd); + break; } - status = ioctl(fd,SND_GET_ENDPOINT, ept); - close(fd); + return status; } @@ -73,6 +128,10 @@ static int snd_get_num(){ return -1; } close(fd); + + /* Add 7 endpoints for the ones we don't get with ioctl */ + mNumSndEndpoints+=7; + return mNumSndEndpoints; } @@ -108,10 +167,6 @@ static int msm72xx_enable_audpp (uint16_t enable_mask) return 0; } -static int set_acoustic_parameters(){ - return 0; -} - AudioHardware::AudioHardware() : mInit(false), mMicMute(true), mBluetoothNrec(true), mBluetoothId(0), mOutput(0), mSndEndpoints(NULL), mCurSndDevice(-1), @@ -136,6 +191,12 @@ AudioHardware::AudioHardware() : LOGI("Not using the proprietary libhtc_acoustic library"); mInit = true; + int rc = set_acoustic_parameters(); + if (rc < 0) { + LOGE("Could not set acoustic parameters to share memory: %d", rc); +// return; + } + mNumSndEndpoints = snd_get_num(); LOGD("mNumSndEndpoints = %d", mNumSndEndpoints); mSndEndpoints = new msm_snd_endpoint[mNumSndEndpoints]; @@ -590,8 +651,8 @@ status_t AudioHardware::doRouting() sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER; audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE); } else { - LOGI("Routing audio to (No microphone) Wired Headset (%d,%x)\n", mMode, outputDevices); - sndDevice = SND_DEVICE_HEADSET; + LOGI("Routing audio to No microphone Wired Headset (%d,%x)\n", mMode, outputDevices); + sndDevice = SND_DEVICE_NO_MIC_HEADSET; } } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) { LOGI("Routing audio to Wired Headset\n");