diff --git a/arch/arm/mach-msm/board-htcleo-audio.c b/arch/arm/mach-msm/board-htcleo-audio.c index bf6d0021..3b2e66c7 100644 --- a/arch/arm/mach-msm/board-htcleo-audio.c +++ b/arch/arm/mach-msm/board-htcleo-audio.c @@ -31,6 +31,11 @@ #include "proc_comm.h" #include "pmic.h" +#include +#include + +#define PROCFS_MAX_SIZE 1024 +#define PROCFS_NAME "mic_level" #if 1 #define D(fmt, args...) printk(KERN_INFO "Audio: "fmt, ##args) @@ -38,6 +43,8 @@ #define D(fmt, args...) do {} while (0) #endif +static struct proc_dir_entry* mic_gain_file; + static struct mutex mic_lock; static struct mutex bt_sco_lock; @@ -111,6 +118,71 @@ static struct q6_hw_info q6_audio_hw[Q6_HW_COUNT] = #endif +//-----------proc file interface-------------------------------- +/** + * This function is called then the /proc file is read + * + */ +int +mic_level_read(char *buffer, + char **buffer_location, + off_t offset, int buffer_length, int *eof, void *data) +{ + int ret; + char temp_buff[1024]; + printk(KERN_INFO "mic_level_read (/proc/%s) called\n", PROCFS_NAME); + + if (offset > 0) { + /* we have finished to read, return 0 */ + ret = 0; + } else { + /* fill the buffer, return the buffer size */ + sprintf(buffer, "Usage: echo 'device_id level' > /proc/mic_level\n"); + strcat(buffer, "Level range: 0-1000; -1 use level from acdb\n"); + strcat(buffer, "Current levels (device_id):\n"); + sprintf(temp_buff, "HANDSET (%d): %d\n", DEVICE_ID_HANDSET_MIC, q6audio_get_tx_dev_volume(DEVICE_ID_HANDSET_MIC)); + strcat(buffer, temp_buff); + sprintf(temp_buff, "SPKR_PHONE (%d): %d\n", DEVICE_ID_SPKR_PHONE_MIC, q6audio_get_tx_dev_volume(DEVICE_ID_SPKR_PHONE_MIC)); + strcat(buffer, temp_buff); + sprintf(temp_buff, "HEADSET (%d): %d\n", DEVICE_ID_HEADSET_MIC, q6audio_get_tx_dev_volume(DEVICE_ID_HEADSET_MIC)); + strcat(buffer, temp_buff); + sprintf(temp_buff, "TTY_HEADSET (%d): %d\n", DEVICE_ID_TTY_HEADSET_MIC, q6audio_get_tx_dev_volume(DEVICE_ID_TTY_HEADSET_MIC)); + strcat(buffer, temp_buff); + sprintf(temp_buff, "BT_SCO (%d): %d\n", DEVICE_ID_BT_SCO_MIC, q6audio_get_tx_dev_volume(DEVICE_ID_BT_SCO_MIC)); + strcat(buffer, temp_buff); + ret = strlen(buffer); + } + return ret; +} + +/** + * This function is called with the /proc file is written + * + */ +int mic_level_write(struct file *file, const char *buffer, unsigned long count, + void *data) +{ + char temp_buff[512]; + int device_id=0, level=0, ret, procfs_buffer_size; + /* get buffer size */ + procfs_buffer_size = count; + if (procfs_buffer_size > 512 ) { + procfs_buffer_size = 512; + } + + /* write data to the buffer */ + if ( copy_from_user(temp_buff, buffer, procfs_buffer_size) ) { + return -EFAULT; + } + sscanf(temp_buff, "%d %d", &device_id, &level); + ret = q6audio_set_tx_dev_volume(device_id, level); + if (ret<0) + return -EFAULT; + procfs_buffer_size=strlen(temp_buff); + return procfs_buffer_size; +} +//-------------------------------------------------------------- + void htcleo_headset_enable(int en) { D("%s %d\n", __func__, en); @@ -286,6 +358,7 @@ void htcleo_analog_init(void) config_gpio_table(bt_sco_disable, ARRAY_SIZE(bt_sco_disable)); gpio_direction_output(HTCLEO_BT_PCM_OUT, 0); mutex_unlock(&bt_sco_lock); + } int htcleo_get_rx_vol(uint8_t hw, int level) @@ -338,6 +411,23 @@ void __init htcleo_audio_init(void) q6audio_register_analog_ops(&ops); acoustic_register_ops(&acoustic); hs_mic_register(); + + mic_gain_file = create_proc_entry(PROCFS_NAME, 0644, NULL); + + if (mic_gain_file == NULL) { + remove_proc_entry(PROCFS_NAME, NULL); + printk(KERN_ALERT "Error: Could not initialize /proc/%s\n", + PROCFS_NAME); + return; + } + + mic_gain_file->read_proc = mic_level_read; + mic_gain_file->write_proc = mic_level_write; + //mic_gain_file->mode = S_IFREG | S_IRUGO; + mic_gain_file->uid = 0; + mic_gain_file->gid = 0; + + printk(KERN_INFO "/proc/%s created\n", PROCFS_NAME); // q6audio_set_acdb_file("default_PMIC.acdb"); } diff --git a/arch/arm/mach-msm/include/mach/msm_qdsp6_audio_1550.h b/arch/arm/mach-msm/include/mach/msm_qdsp6_audio_1550.h index 4f3c4a5b..47306ec9 100644 --- a/arch/arm/mach-msm/include/mach/msm_qdsp6_audio_1550.h +++ b/arch/arm/mach-msm/include/mach/msm_qdsp6_audio_1550.h @@ -52,6 +52,14 @@ struct audio_client { #define Q6_HW_COUNT 6 +#define DEVICE_ID_HANDSET_MIC 0 +#define DEVICE_ID_SPKR_PHONE_MIC 1 +#define DEVICE_ID_HEADSET_MIC 2 +#define DEVICE_ID_TTY_HEADSET_MIC 3 +#define DEVICE_ID_BT_SCO_MIC 4 +#define DEVICE_ID_MIC_COUNT 5 +#define MAX_MIC_LEVEL 1000 + struct q6_hw_info { int min_gain; int max_gain; @@ -95,6 +103,8 @@ int q6audio_update_acdb(uint32_t id_src, uint32_t id_dst); int q6audio_set_rx_volume(int level); int q6audio_set_rx_mute(int mute); int q6audio_set_stream_volume(struct audio_client *ac, int vol); +int q6audio_set_tx_dev_volume(int device_id, int level); +int q6audio_get_tx_dev_volume(int device_id); struct q6audio_analog_ops { void (*init)(void); diff --git a/arch/arm/mach-msm/qdsp6_1550/q6audio.c b/arch/arm/mach-msm/qdsp6_1550/q6audio.c index 6dd1f915..cda144ef 100644 --- a/arch/arm/mach-msm/qdsp6_1550/q6audio.c +++ b/arch/arm/mach-msm/qdsp6_1550/q6audio.c @@ -56,6 +56,46 @@ #define CB_EVENT_COOKIE 0xC00CE13E +struct mic_level{ + int device_id; + int level; +}; + +// same gain range is used for every mic +static int min_mic_gain = -5000; +static int max_mic_gain = 1500; +/* +* level range 0 - 1000 +* level -1 -> level is not defined by user so default value(gain) is set through acbd firmware +*/ +static struct mic_level user_mic_levels[DEVICE_ID_MIC_COUNT] = +{ + [0] = + { + .device_id = ADSP_AUDIO_DEVICE_ID_HANDSET_MIC, + .level = -1 + }, + [1] = + { + .device_id = ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_MIC, + .level = -1 + }, + [2] = + { + .device_id = ADSP_AUDIO_DEVICE_ID_HEADSET_MIC, + .level = -1 + }, + [3] = + { + .device_id = ADSP_AUDIO_DEVICE_ID_TTY_HEADSET_MIC, + .level = -1 + }, + [4] = + { + .device_id = ADSP_AUDIO_DEVICE_ID_BT_SCO_MIC, + .level = -1 + } +}; #if 1 @@ -141,6 +181,7 @@ static DEFINE_MUTEX(idlecount_lock); void audio_prevent_sleep(void) { + AUDIO_INFO("%s\n", __func__); mutex_lock(&idlecount_lock); if (++idlecount == 1) { wake_lock(&wakelock); @@ -151,6 +192,7 @@ void audio_prevent_sleep(void) void audio_allow_sleep(void) { + AUDIO_INFO("%s\n", __func__); mutex_lock(&idlecount_lock); if (--idlecount == 0) { wake_unlock(&idlelock); @@ -181,12 +223,14 @@ static int acdb_use_map = 0; void q6audio_register_analog_ops(struct q6audio_analog_ops *ops) { + AUDIO_INFO("%s\n", __func__); pr_info("register analog ops = %p\n", ops); analog_ops = ops; } void q6audio_set_acdb_file(char* filename) { + AUDIO_INFO("%s\n", __func__); if (filename) { pr_info("audio: set acdb file as %s\n", filename); strncpy(acdb_file, filename, sizeof(acdb_file)-1); @@ -196,6 +240,7 @@ void q6audio_set_acdb_file(char* filename) static struct q6_device_info *q6_lookup_device(uint32_t device_id) { struct q6_device_info *di = q6_audio_devices; + AUDIO_INFO("%s\n", __func__); for (;;) { if (di->id == device_id) return di; @@ -211,36 +256,42 @@ static struct q6_device_info *q6_lookup_device(uint32_t device_id) static uint32_t q6_device_to_codec(uint32_t device_id) { struct q6_device_info *di = q6_lookup_device(device_id); + AUDIO_INFO("%s\n", __func__); return di->codec; } static uint32_t q6_device_to_dir(uint32_t device_id) { struct q6_device_info *di = q6_lookup_device(device_id); + AUDIO_INFO("%s\n", __func__); return di->dir; } static uint32_t q6_device_to_cad_id(uint32_t device_id) { struct q6_device_info *di = q6_lookup_device(device_id); + AUDIO_INFO("%s\n", __func__); return di->cad_id; } static uint32_t q6_device_to_path(uint32_t device_id) { struct q6_device_info *di = q6_lookup_device(device_id); + AUDIO_INFO("%s\n", __func__); return di->path; } static uint32_t q6_device_to_rate(uint32_t device_id) { struct q6_device_info *di = q6_lookup_device(device_id); + AUDIO_INFO("%s\n", __func__); return di->rate; } int q6_device_volume(uint32_t device_id, int level) { struct q6_device_info *di = q6_lookup_device(device_id); + AUDIO_INFO("%s\n", __func__); if (analog_ops->get_rx_vol) return analog_ops->get_rx_vol(di->hw, level); else { @@ -267,12 +318,14 @@ static inline int adie_close(struct dal_client *client) static inline int adie_set_path(struct dal_client *client, uint32_t id, uint32_t path_type) { + AUDIO_INFO("%s\n", __func__); return dal_call_f1(client, ADIE_OP_SET_PATH, id, path_type); } static inline int adie_set_path_freq_plan(struct dal_client *client, uint32_t path_type, uint32_t plan) { + AUDIO_INFO("%s\n", __func__); return dal_call_f1(client, ADIE_OP_SET_PATH_FREQUENCY_PLAN, path_type, plan); } @@ -280,6 +333,7 @@ static inline int adie_set_path_freq_plan(struct dal_client *client, static inline int adie_proceed_to_stage(struct dal_client *client, uint32_t path_type, uint32_t stage) { + AUDIO_INFO("%s\n", __func__); return dal_call_f1(client, ADIE_OP_PROCEED_TO_STAGE, path_type, stage); } @@ -287,6 +341,7 @@ static inline int adie_proceed_to_stage(struct dal_client *client, static inline int adie_mute_path(struct dal_client *client, uint32_t path_type, uint32_t mute_state) { + AUDIO_INFO("%s\n", __func__); return dal_call_f1(client, ADIE_OP_MUTE_PATH, path_type, mute_state); } @@ -298,6 +353,7 @@ static struct dal_client *acdb; static int adie_enable(void) { + AUDIO_INFO("%s\n", __func__); adie_refcount++; if (adie_refcount == 1) adie_open(adie); @@ -306,6 +362,7 @@ static int adie_enable(void) static int adie_disable(void) { + AUDIO_INFO("%s\n", __func__); adie_refcount--; if (adie_refcount == 0) adie_close(adie); @@ -336,6 +393,7 @@ static int session_alloc(struct audio_client *ac) { int n; + AUDIO_INFO("%s\n", __func__); mutex_lock(&session_lock); for (n = SESSION_MIN; n < SESSION_MAX; n++) { if (!session[n]) { @@ -350,6 +408,7 @@ static int session_alloc(struct audio_client *ac) static void session_free(int n, struct audio_client *ac) { + AUDIO_INFO("%s\n", __func__); mutex_lock(&session_lock); if (session[n] == ac) session[n] = 0; @@ -358,6 +417,7 @@ static void session_free(int n, struct audio_client *ac) void audio_client_dump(struct audio_client *ac) { + AUDIO_INFO("%s\n", __func__); dal_trace_dump(ac->client); } @@ -452,6 +512,7 @@ fail_session: static int audio_ioctl(struct audio_client *ac, uint32_t cmd, void *ptr, uint32_t len) { int r; + AUDIO_INFO("%s\n", __func__); r = dal_call_f6(ac->client, AUDIO_OP_IOCTL, cmd, ptr, len); return r; } @@ -459,6 +520,7 @@ static int audio_ioctl(struct audio_client *ac, uint32_t cmd, void *ptr, uint32_ static int audio_command(struct audio_client *ac, uint32_t cmd) { struct adsp_command_hdr rpc; + AUDIO_INFO("%s %x\n", __func__, cmd); memset(&rpc, 0, sizeof(rpc)); return audio_ioctl(ac, cmd, NULL, 0); } @@ -468,6 +530,7 @@ static int audio_open_control(struct audio_client *ac) int r; struct adsp_open_command rpc; + AUDIO_INFO("%s\n", __func__); memset(&rpc, 0, sizeof(rpc)); rpc.opcode = ADSP_AUDIO_OPCODE_OPEN_DEV; @@ -494,6 +557,7 @@ static int audio_out_open(struct audio_client *ac, uint32_t bufsz, struct adsp_open_command rpc; union adsp_audio_format *ptr; + AUDIO_INFO("%s\n", __func__); printk("audio_out_open: %x %d %d\n", bufsz, rate, channels); mutex_lock(&open_mem_lock); @@ -536,6 +600,7 @@ static int audio_out_open(struct audio_client *ac, uint32_t bufsz, // return r; return ac->open_status; } +static void update_all_audio_tx_volume(struct audio_client *ac); static int audio_in_open(struct audio_client *ac, uint32_t bufsz, #ifdef CONFIG_QSD_AUDIO_CALLREC @@ -547,6 +612,7 @@ static int audio_in_open(struct audio_client *ac, uint32_t bufsz, struct adsp_open_command rpc; union adsp_audio_format *ptr; + AUDIO_INFO("%s\n", __func__); printk("audio_in_open: %x %d %d\n", bufsz, rate, channels); mutex_lock(&open_mem_lock); memset(&rpc, 0, sizeof(rpc)); @@ -598,6 +664,7 @@ static int audio_mp3_open(struct audio_client *ac, uint32_t bufsz, struct adsp_open_command rpc; union adsp_audio_format *ptr; + AUDIO_INFO("%s\n", __func__); printk("audio_mp3_open: %x %d %d\n", bufsz, rate, channels); mutex_lock(&open_mem_lock); memset(&rpc, 0, sizeof(rpc)); @@ -644,6 +711,7 @@ static int audio_aac_open(struct audio_client *ac, uint32_t bufsz, void *data) union adsp_audio_format *ptr; + AUDIO_INFO("%s\n", __func__); mutex_lock(&open_mem_lock); memset(&rpc, 0, sizeof(rpc)); ptr = (union adsp_audio_format*)params_data; @@ -783,13 +851,14 @@ static int audio_qcelp_open(struct audio_client *ac, uint32_t bufsz, struct msm_audio_qcelp_config *qf = data; struct adsp_open_command rpc; struct adsp_audio_standard_format *fmt; - union adsp_audio_format *ptr; +// union adsp_audio_format *ptr; + AUDIO_INFO("%s\n", __func__); mutex_lock(&open_mem_lock); memset(&rpc, 0, sizeof(rpc)); fmt = (struct adsp_audio_standard_format *)params_data; - memset(ptr, 0, sizeof(struct adsp_audio_standard_format)); + memset(fmt, 0, sizeof(struct adsp_audio_standard_format)); rpc.numdev = 1; rpc.dev[0] = ADSP_AUDIO_DEVICE_ID_DEFAULT; @@ -818,6 +887,7 @@ static int audio_qcelp_open(struct audio_client *ac, uint32_t bufsz, static int audio_close(struct audio_client *ac) { + AUDIO_INFO("%s\n", __func__); AUDIO_INFO("%p: close\n", ac); audio_command(ac, ADSP_AUDIO_IOCTL_CMD_STREAM_STOP); // audio_command(ac, ADSP_AUDIO_IOCTL_CMD_CLOSE); @@ -893,7 +963,7 @@ static int audio_rx_volume(struct audio_client *ac, uint32_t dev_id, int32_t vol { struct adsp_set_dev_volume_command rpc; - AUDIO_INFO("%s: dev_id 0x%08x, volume = %d\n", __func__, dev_id , volume); + AUDIO_INFO("%s: ac: %p dev_id 0x%08x, volume = %d\n", __func__, ac, dev_id , volume); memset(&rpc, 0, sizeof(rpc)); rpc.device_id = dev_id; @@ -906,7 +976,7 @@ static int audio_tx_volume(struct audio_client *ac, uint32_t dev_id, int32_t vol { struct adsp_set_dev_volume_command rpc; - AUDIO_INFO("%s: dev_id 0x%08x, volume = %d\n", __func__, dev_id , volume); + AUDIO_INFO("%s: %p dev_id 0x%08x, volume = %d\n", __func__, ac, dev_id , volume); memset(&rpc, 0, sizeof(rpc)); rpc.device_id = dev_id; @@ -1012,6 +1082,7 @@ static void callback(void *data, int len, void *cookie) struct adsp_audio_event* ae; // printk("dal event\n"); + AUDIO_INFO("%s audio callback: CB: %X LOC: %X SIZE=%X, event_id = %X\n", __func__, e->cb_evt, e->loc_evt, e->size, e->ae.event_id); TRACE("audio callback: CB: %X LOC: %X SIZE=%X\n", e->cb_evt, e->loc_evt, e->size); if (e->cb_evt != CB_EVENT_COOKIE) @@ -1162,7 +1233,7 @@ static int acdb_init(char *filename) int n; // return -ENODEV; - + AUDIO_INFO("%s\n", __func__); #ifdef CONFIG_MACH_HTCLEO pr_info("acdb: trying htcleo.acdb\n"); if(request_firmware(&fw, "htcleo.acdb", q6_control_device.this_device) < 0) { @@ -1234,6 +1305,7 @@ static int q6audio_init(void) if (ac_control) { res = 0; + AUDIO_INFO("%s no init all done\n", __func__); goto done; } @@ -1245,6 +1317,7 @@ static int q6audio_init(void) sdac_clk = clk_get(0, "sdac_clk"); audio_data = dma_alloc_coherent(NULL, 4096, &audio_phys, GFP_KERNEL); params_data = dma_alloc_coherent(NULL, 4096, ¶ms_phys, GFP_KERNEL); + AUDIO_INFO("%s allocated", __func__); // printk("allocated: %p %x\n", params_data, params_phys); // pr_info("audio: init: INIT\n"); @@ -1326,6 +1399,7 @@ done: static int map_cad_dev_to_virtual(int cd) { + AUDIO_INFO("%s\n", __func__); if (global_now_phone_call) { return cd; @@ -1535,7 +1609,7 @@ static int audio_update_acdb(uint32_t adev, uint32_t acdb_id) int sz = -1; printk("%s (%d, %d)\n", __func__, adev, acdb_id); - AUDIO_INFO("%s (%d, %d)\n", __func__, adev, acdb_id); + AUDIO_INFO("%s (%x, %d)\n", __func__, adev, acdb_id); // dex_comm(PCOM_UPDATE_ACDB, 0, 0); sample_rate = q6_device_to_rate(adev); @@ -1553,12 +1627,14 @@ static int audio_update_acdb(uint32_t adev, uint32_t acdb_id) { acdb_id = q6_device_to_cad_id(adev); printk(" new acdb = %d\n", acdb_id); + AUDIO_INFO(" new acdb = %d\n", acdb_id); sz = acdb_get_config_table(acdb_id, sample_rate); } printk("res2 = %d\n", sz); if (sz > 0) { printk("call audio_set_table\n"); + AUDIO_INFO("call audio_set_table\n"); audio_set_table(ac_control, adev, sz); } return 0; @@ -1567,6 +1643,7 @@ static int audio_update_acdb(uint32_t adev, uint32_t acdb_id) #ifdef CONFIG_QSD_AUDIO_CALLREC static void adie_rx_path_enable(uint32_t acdb_id) { + AUDIO_INFO("%s\n", __func__); if (audio_rx_path_id) { adie_enable(); adie_set_path(adie, audio_rx_path_id, ADIE_PATH_RX); @@ -1581,6 +1658,7 @@ static void adie_rx_path_enable(uint32_t acdb_id) static void q6_rx_path_enable(int reconf, uint32_t acdb_id) { + AUDIO_INFO("%s\n", __func__); audio_update_acdb(audio_rx_device_id, acdb_id); if (!reconf) qdsp6_devchg_notify(ac_control, ADSP_AUDIO_RX_DEVICE, audio_rx_device_id); @@ -1609,6 +1687,56 @@ static void _audio_rx_path_enable(int reconf, uint32_t acdb_id) audio_rx_analog_enable(1); } +//function to calculate mic gain; for now we use the same gain range for all mic +static int get_audio_tx_volume(uint32_t device_id, int level) +{ + AUDIO_INFO("%s\n", __func__); + return min_mic_gain + ((max_mic_gain - min_mic_gain) * level) / MAX_MIC_LEVEL; +} + +static DEFINE_MUTEX(audio_path_lock); +static int audio_rx_path_refcount; +static int audio_tx_path_refcount; + +static void _update_audio_tx_volume(struct audio_client *ac, uint32_t dev_id) +{ + int i, level = -1, volume, ret; + AUDIO_INFO("%s device_id %x\n", __func__, dev_id); + for (i = 0; i < DEVICE_ID_MIC_COUNT; i++ ) { + if (user_mic_levels[i].device_id == dev_id) + { + level = user_mic_levels[i].level; + break; + } + } + if (level==-1) + { + AUDIO_INFO("%s returning level = -1\n", __func__); + return; + } + volume = get_audio_tx_volume(dev_id, level); + ret = audio_tx_volume(ac, dev_id, volume); + AUDIO_INFO("%s device_id = %x, level= %d, volume= %d, ret = %d", __func__, dev_id, level, volume, ret); + return; +} + +static void update_all_audio_tx_volume(struct audio_client *ac) +{ + int i, volume, ret; + AUDIO_INFO("%s\n", __func__); + for (i = 0; i < DEVICE_ID_MIC_COUNT; i++ ) { + if (user_mic_levels[i].level==-1) + { + continue; + } + mutex_lock(&audio_path_lock); + volume = get_audio_tx_volume(user_mic_levels[i].device_id, user_mic_levels[i].level); + ret = audio_tx_volume(ac, user_mic_levels[i].device_id, volume); + mutex_unlock(&audio_path_lock); + AUDIO_INFO("%s device_id = %x, level= %d, volume= %d, ret = %d", __func__, user_mic_levels[i].device_id, user_mic_levels[i].level, volume, ret); + } + return; +} static void _audio_tx_path_enable(int reconf, uint32_t acdb_id) { @@ -1632,8 +1760,8 @@ static void _audio_tx_path_enable(int reconf, uint32_t acdb_id) qdsp6_devchg_notify(ac_control, ADSP_AUDIO_TX_DEVICE, audio_tx_device_id); qdsp6_standby(ac_control); qdsp6_start(ac_control); - audio_tx_mute(ac_control, audio_tx_device_id, tx_mute_status); + _update_audio_tx_volume(ac_control, audio_tx_device_id); } static void _audio_rx_path_disable(void) @@ -1860,9 +1988,6 @@ static void _audio_tx_clk_reinit(uint32_t tx_device) _audio_tx_clk_enable(); } -static DEFINE_MUTEX(audio_path_lock); -static int audio_rx_path_refcount; -static int audio_tx_path_refcount; static int audio_rx_path_enable(int en, uint32_t acdb_id) { @@ -1910,6 +2035,7 @@ int q6audio_reinit_acdb(char* filename) { int res; + AUDIO_INFO("%s\n", __func__); if (q6audio_init()) return 0; @@ -1931,6 +2057,7 @@ int q6audio_update_acdb(uint32_t id_src, uint32_t id_dst) { int res; + AUDIO_INFO("%s\n", __func__); if (q6audio_init()) return 0; @@ -1950,11 +2077,49 @@ done: return res; } + +int q6audio_get_tx_dev_volume(int device_id) +{ + AUDIO_INFO("%s\n", __func__); + if (device_id > DEVICE_ID_MIC_COUNT || device_id < 0) + { + pr_err("unsupported device id %d\n", device_id); + return -EINVAL; + } + return user_mic_levels[device_id].level; +} + + +int q6audio_set_tx_dev_volume(int device_id, int level) +{ + AUDIO_INFO("%s\n", __func__); + if (level < -1) + level = -1; + if (level > MAX_MIC_LEVEL) + level = MAX_MIC_LEVEL; + if (device_id > DEVICE_ID_MIC_COUNT || device_id < 0) + { + AUDIO_INFO("%s unsupported device id %d\n", __func__, device_id); + pr_err("unsupported device id %d\n", device_id); + return -EINVAL; + } + user_mic_levels[device_id].level = level; + if (ac_control) + { + mutex_lock(&audio_path_lock); + _update_audio_tx_volume(ac_control, user_mic_levels[device_id].device_id); + mutex_unlock(&audio_path_lock); + + } + + return 0; +} + int q6audio_set_tx_mute(int mute) { uint32_t adev; - AUDIO_INFO("%s\n", __func__); + AUDIO_INFO("%s mute= %d\n", __func__, mute); if (q6audio_init()) return 0; @@ -1962,19 +2127,22 @@ int q6audio_set_tx_mute(int mute) if (mute == tx_mute_status) { mutex_unlock(&audio_path_lock); + AUDIO_INFO("%s no change %d\n", __func__, mute); return 0; } adev = audio_tx_device_id; audio_tx_mute(ac_control, adev, mute); tx_mute_status = mute; + if (!mute) + _update_audio_tx_volume(ac_control, audio_tx_device_id); mutex_unlock(&audio_path_lock); return 0; } int q6audio_set_stream_volume(struct audio_client *ac, int vol) { - AUDIO_INFO("%s\n", __func__); + AUDIO_INFO("%s %d\n", __func__, vol); if (vol > 1200 || vol < -4000) { pr_err("unsupported volume level %d\n", vol); return -EINVAL; @@ -2007,7 +2175,10 @@ int q6audio_set_rx_dev_volume(int level) vol = q6_device_volume(audio_rx_device_id, level); printk("$$ DEV=%08X: vol is %d\n", audio_rx_device_id, vol); audio_rx_volume(ac_control, audio_rx_device_id, vol); - + //this is needed beacause some audio library don't do + // mic mute -> mic unmute when the call is made, + // instead library is constantly seting audio volume + _update_audio_tx_volume(ac_control, audio_tx_device_id); mutex_unlock(&audio_path_lock); return 0; } @@ -2034,6 +2205,7 @@ int q6audio_set_rx_volume(int level) rx_vol_level = level; mutex_unlock(&audio_path_lock); #else + AUDIO_INFO("%s\n", __func__); q6audio_set_rx_dev_volume(level); #endif return 0; @@ -2118,6 +2290,8 @@ static void do_tx_routing(uint32_t device_id, uint32_t acdb_id) qdsp6_standby(ac_control); qdsp6_start(ac_control); } + AUDIO_INFO("%s, update_tx_volume", __func__); + _update_audio_tx_volume(ac_control, device_id); return; } @@ -2129,6 +2303,8 @@ static void do_tx_routing(uint32_t device_id, uint32_t acdb_id) } else { audio_tx_device_id = device_id; audio_tx_path_id = q6_device_to_path(device_id); + AUDIO_INFO("%s, update_tx_volume2", __func__); + _update_audio_tx_volume(ac_control, audio_tx_device_id); } } @@ -2195,7 +2371,7 @@ struct audio_client *q6audio_open_pcm(uint32_t bufsz, uint32_t rate, int rc, retry = 5; struct audio_client *ac; - AUDIO_INFO("%s\n", __func__); + AUDIO_INFO("%s write= %d \n", __func__, flags& AUDIO_FLAG_WRITE); if (q6audio_init()) return 0; @@ -2341,6 +2517,11 @@ struct audio_client *q6audio_open_pcm(uint32_t bufsz, uint32_t rate, } audio_prevent_sleep(); + if (!(ac->flags & AUDIO_FLAG_WRITE)) + { + update_all_audio_tx_volume(ac_control); + } + return ac; #else return audio_test(); @@ -2380,6 +2561,10 @@ struct audio_client *q6voice_open(uint32_t flags, uint32_t acdb_id) } else { tx_clk_freq = 8000; audio_tx_path_enable(1, acdb_id); + AUDIO_INFO("%s start session\n", __func__); + // this is a good location for updating the mic gain but + // for some reason this doesn't work (too early to set mic gain) + //update_all_audio_tx_volume(ac_control); } return ac; @@ -2403,6 +2588,7 @@ struct audio_client *q6audio_open_mp3(uint32_t bufsz, uint32_t rate, { struct audio_client *ac; + AUDIO_INFO("%s\n", __func__); printk("q6audio_open_mp3()\n"); if (q6audio_init()) @@ -2433,6 +2619,7 @@ int q6audio_mp3_close(struct audio_client *ac) int q6audio_async(struct audio_client *ac) { struct adsp_command_hdr rpc; + AUDIO_INFO("%s\n", __func__); memset(&rpc, 0, sizeof(rpc)); // rpc.response_type = ADSP_AUDIO_RESPONSE_ASYNC; return audio_ioctl(ac, ADSP_AUDIO_IOCTL_CMD_STREAM_EOS, &rpc, sizeof(rpc)); @@ -2445,6 +2632,7 @@ struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t rate, { struct audio_client *ac; + AUDIO_INFO("%s\n", __func__); TRACE("q6audio_open_aac flags=%d rate=%d\n", flags, rate); if (q6audio_init()) @@ -2478,6 +2666,7 @@ struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t rate, int q6audio_aac_close(struct audio_client *ac) { + AUDIO_INFO("%s\n", __func__); audio_close(ac); if (ac->flags & AUDIO_FLAG_WRITE) audio_rx_path_enable(0, 0); @@ -2493,6 +2682,7 @@ struct audio_client *q6fm_open(void) { struct audio_client *ac; + AUDIO_INFO("%s\n", __func__); printk("q6fm_open()\n"); if (q6audio_init()) @@ -2515,6 +2705,7 @@ struct audio_client *q6fm_open(void) int q6fm_close(struct audio_client *ac) { + AUDIO_INFO("%s\n", __func__); printk("q6fm_close\n"); audio_rx_path_enable(0, 0); @@ -2551,11 +2742,13 @@ struct audio_client *q6audio_open_qcelp(uint32_t bufsz, uint32_t rate, q6audio_read(ac, &ac->buf[1]); audio_prevent_sleep(); + update_all_audio_tx_volume(ac_control); return ac; } int q6audio_qcelp_close(struct audio_client *ac) { + AUDIO_INFO("%s\n", __func__); audio_close(ac); audio_tx_path_enable(0, 0); audio_client_free(ac); @@ -2571,6 +2764,7 @@ int acdb_get_table(int dev_id, int sample_rate) struct acdb_result res; int r; + AUDIO_INFO("%s\n", __func__); memset(audio_data, 0, 4096); memset(&rpc, 0, sizeof(rpc)); @@ -2600,6 +2794,7 @@ static struct audio_client * audio_test(void) int size; struct rpc_info info; + AUDIO_INFO("%s\n", __func__); pr_info("audio: init: codecs\n"); icodec_rx_clk = clk_get(0, "icodec_rx_clk"); icodec_tx_clk = clk_get(0, "icodec_tx_clk");