ASoC: msm: qdsp6v2: Add control for ICC Volume

Add control via ADM set PP Params to control volume of ICC
through a mixer command "Internal ICC Volume".

CRs-fixed: 1025376
Change-Id: I2b7099fe6d3a510859af42f1ac37a6db6e1b453c
Signed-off-by: Derek Chen <chenche@codeaurora.org>
This commit is contained in:
Derek Chen 2016-06-06 20:40:29 -04:00 committed by Gerrit - the friendly Code Review server
parent 08a95e6878
commit b5e3d1e282
4 changed files with 117 additions and 1 deletions

View file

@ -6768,6 +6768,12 @@ struct admx_mic_gain {
/*< Clients must set this field to zero. */
} __packed;
struct adm_set_mic_gain_params {
struct adm_cmd_set_pp_params_v5 params;
struct adm_param_data_v5 data;
struct admx_mic_gain mic_gain_data;
} __packed;
/* end_addtogroup audio_pp_param_ids */
/* @ingroup audio_pp_module_ids

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -130,6 +130,8 @@ int adm_set_volume(int port_id, int copp_idx, int volume);
int adm_set_softvolume(int port_id, int copp_idx,
struct audproc_softvolume_params *softvol_param);
int adm_set_mic_gain(int port_id, int copp_idx, int volume);
int adm_param_enable(int port_id, int copp_idx, int module_id, int enable);
int adm_send_calibration(int port_id, int copp_idx, int path, int perf_mode,

View file

@ -81,6 +81,10 @@ static int msm_route_hfp_vol_control;
static const DECLARE_TLV_DB_LINEAR(hfp_rx_vol_gain, 0,
INT_RX_VOL_MAX_STEPS);
static int msm_route_icc_vol_control;
static const DECLARE_TLV_DB_LINEAR(icc_rx_vol_gain, 0,
INT_RX_VOL_MAX_STEPS);
static int msm_route_pri_auxpcm_lb_vol_ctrl;
static const DECLARE_TLV_DB_LINEAR(pri_auxpcm_lb_vol_gain, 0,
INT_RX_VOL_MAX_STEPS);
@ -493,6 +497,23 @@ static int msm_qti_pp_set_slimbus_8_lb_vol_mixer(struct snd_kcontrol *kcontrol,
return ret;
}
static int msm_qti_pp_get_icc_vol_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = msm_route_icc_vol_control;
return 0;
}
static int msm_qti_pp_set_icc_vol_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
adm_set_mic_gain(AFE_PORT_ID_QUATERNARY_TDM_TX,
adm_get_default_copp_idx(AFE_PORT_ID_QUATERNARY_TDM_TX),
ucontrol->value.integer.value[0]);
msm_route_icc_vol_control = ucontrol->value.integer.value[0];
return 0;
}
static int msm_qti_pp_get_quat_mi2s_fm_vol_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@ -809,6 +830,12 @@ static const struct snd_kcontrol_new int_hfp_vol_mixer_controls[] = {
msm_qti_pp_set_hfp_vol_mixer, hfp_rx_vol_gain),
};
static const struct snd_kcontrol_new int_icc_vol_mixer_controls[] = {
SOC_SINGLE_EXT_TLV("Internal ICC Volume", SND_SOC_NOPM, 0,
INT_RX_VOL_GAIN, 0, msm_qti_pp_get_icc_vol_mixer,
msm_qti_pp_set_icc_vol_mixer, icc_rx_vol_gain),
};
static const struct snd_kcontrol_new pri_auxpcm_lb_vol_mixer_controls[] = {
SOC_SINGLE_EXT_TLV("PRI AUXPCM LOOPBACK Volume",
AFE_PORT_ID_PRIMARY_PCM_TX, 0, INT_RX_VOL_GAIN, 0,
@ -1001,6 +1028,9 @@ void msm_qti_pp_add_controls(struct snd_soc_platform *platform)
snd_soc_add_platform_controls(platform, int_hfp_vol_mixer_controls,
ARRAY_SIZE(int_hfp_vol_mixer_controls));
snd_soc_add_platform_controls(platform, int_icc_vol_mixer_controls,
ARRAY_SIZE(int_icc_vol_mixer_controls));
snd_soc_add_platform_controls(platform,
pri_auxpcm_lb_vol_mixer_controls,
ARRAY_SIZE(pri_auxpcm_lb_vol_mixer_controls));

View file

@ -3471,6 +3471,84 @@ fail_cmd:
return rc;
}
int adm_set_mic_gain(int port_id, int copp_idx, int volume)
{
struct adm_set_mic_gain_params mic_gain_params;
int rc = 0;
int sz, port_idx;
pr_debug("%s:\n", __func__);
port_id = afe_convert_virtual_to_portid(port_id);
port_idx = adm_validate_and_get_port_index(port_id);
if (port_idx < 0) {
pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
return -EINVAL;
}
sz = sizeof(struct adm_set_mic_gain_params);
mic_gain_params.params.hdr.hdr_field =
APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
mic_gain_params.params.hdr.pkt_size = sz;
mic_gain_params.params.hdr.src_svc = APR_SVC_ADM;
mic_gain_params.params.hdr.src_domain = APR_DOMAIN_APPS;
mic_gain_params.params.hdr.src_port = port_id;
mic_gain_params.params.hdr.dest_svc = APR_SVC_ADM;
mic_gain_params.params.hdr.dest_domain = APR_DOMAIN_ADSP;
mic_gain_params.params.hdr.dest_port =
atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
mic_gain_params.params.hdr.token = port_idx << 16 | copp_idx;
mic_gain_params.params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
mic_gain_params.params.payload_addr_lsw = 0;
mic_gain_params.params.payload_addr_msw = 0;
mic_gain_params.params.mem_map_handle = 0;
mic_gain_params.params.payload_size =
sizeof(struct adm_param_data_v5) +
sizeof(struct admx_mic_gain);
mic_gain_params.data.module_id = ADM_MODULE_IDX_MIC_GAIN_CTRL;
mic_gain_params.data.param_id = ADM_PARAM_IDX_MIC_GAIN;
mic_gain_params.data.param_size =
sizeof(struct admx_mic_gain);
mic_gain_params.data.reserved = 0;
mic_gain_params.mic_gain_data.tx_mic_gain = volume;
mic_gain_params.mic_gain_data.reserved = 0;
pr_debug("%s: Mic Gain set to %d at port_id 0x%x\n",
__func__, volume, port_id);
atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
rc = apr_send_pkt(this_adm.apr, (uint32_t *)&mic_gain_params);
if (rc < 0) {
pr_err("%s: Set params failed port = %#x\n",
__func__, port_id);
rc = -EINVAL;
goto fail_cmd;
}
/* Wait for the callback */
rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
msecs_to_jiffies(TIMEOUT_MS));
if (!rc) {
pr_err("%s: Mic Gain Set params timed out port = %#x\n",
__func__, port_id);
rc = -EINVAL;
goto fail_cmd;
} else if (atomic_read(&this_adm.copp.stat
[port_idx][copp_idx]) > 0) {
pr_err("%s: DSP returned error[%s]\n",
__func__, adsp_err_get_err_str(
atomic_read(&this_adm.copp.stat
[port_idx][copp_idx])));
rc = adsp_err_get_lnx_err_code(
atomic_read(&this_adm.copp.stat
[port_idx][copp_idx]));
goto fail_cmd;
}
rc = 0;
fail_cmd:
return rc;
}
int adm_param_enable(int port_id, int copp_idx, int module_id, int enable)
{
struct audproc_enable_param_t adm_mod_enable;