htcleo: audio: add proc file interface /proc/mic_level and fix mic gain (Credits to mdebeljuh and jdivic)

Apply the diff file from http://forum.xda-developers.com/showpost.php?p=17031938&postcount=97
Disable debug output and fix typo by tytung.

Usage: echo 'device_id level' > /proc/mic_level
Level range: 0-1000; -1 use level from acdb
Current levels (device_id):
HANDSET (0): -1
SPKR_PHONE (1): -1
HEADSET (2): -1
TTY_HEADSET (3): -1
BT_SCO (4): -1
This commit is contained in:
tytung 2011-08-29 22:07:47 +08:00
parent 343845b70a
commit ca26744fe2
3 changed files with 309 additions and 14 deletions

View File

@ -31,6 +31,11 @@
#include "proc_comm.h"
#include "pmic.h"
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#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");
}

View File

@ -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);

View File

@ -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, &params_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");