msm-audio: adding mixer control for soft step volume params

adding new mixer control for set/get soft step volume module params
values. This command is attached to FE DAI.

Change-Id: I2572d6abe48dcb4d1fb685b5e9c0695fe83cc88a
Signed-off-by: Krishna Kishor Jha <quic_kkishorj@quicinc.com>
This commit is contained in:
Krishna Kishor Jha 2022-02-21 18:43:37 +05:30 • committed by Gerrit - the friendly Code Review server
commit 91c556699a
4 changed files with 284 additions and 0 deletions

187
asoc/msm-pcm-q6-v2.c Normal file → Executable file
View file

@ -129,6 +129,8 @@ static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
.mask = 0,
};
static struct asm_softvolume_params soft_params = {0,0,0};
struct msm_pcm_channel_map *chmap_pspd[MSM_FRONTEND_DAI_MM_SIZE][2];
static void msm_pcm_route_event_handler(enum msm_pcm_routing_event event,
@ -151,6 +153,181 @@ static void msm_pcm_route_event_handler(enum msm_pcm_routing_event event,
}
}
static int msm_pcm_set_soft_volume_params(struct msm_audio *prtd,struct asm_softvolume_params *soft_vol_params)
{
int rc = 0;
switch (prtd->audio_client->topology) {
default:
rc = q6asm_set_softvolume_v2(prtd->audio_client, soft_vol_params,
SOFT_VOLUME_INSTANCE_1);
if (rc < 0)
pr_err("%s: Send SoftVolume Param failed ret=%d\n",
__func__, rc);
}
return rc;
}
static int msm_pcm_soft_volume_ctl_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_pcm_soft_volume *soft_vol = (struct snd_pcm_soft_volume *) snd_kcontrol_chip(kcontrol);
struct msm_plat_data *pdata = NULL;
struct snd_pcm_substream *substream = NULL;
struct snd_soc_pcm_runtime *soc_prtd = NULL;
struct snd_soc_component *component = NULL;
pr_debug("%s\n", __func__);
if (!soft_vol || !soft_vol->pcm) {
pr_err("%s: soft vol is NULL\n", __func__);
return -ENODEV;
}
substream = soft_vol->pcm->streams[soft_vol->stream].substream;
if (!substream) {
pr_err("%s substream not found\n", __func__);
return -ENODEV;
}
soc_prtd = substream->private_data;
if (!soc_prtd) {
pr_err("%s substream runtime or private_data not found\n",
__func__);
return -ENODEV;
}
component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
if (!component || !component->dev) {
pr_err("%s: component is NULL\n", __func__);
return -ENODEV;
}
pdata = (struct msm_plat_data *) dev_get_drvdata(component->dev);
if (!pdata) {
pr_err("%s: pdata not found\n", __func__);
return -ENODEV;
}
mutex_lock(&pdata->lock);
ucontrol->value.integer.value[0] = soft_params.period;
ucontrol->value.integer.value[1] = soft_params.step;
ucontrol->value.integer.value[2] = soft_params.rampingcurve;
pr_debug("%s: period = %d, step = %d , ramping curve: %d",__func__,
ucontrol->value.integer.value[0],
ucontrol->value.integer.value[1],
ucontrol->value.integer.value[2]);
mutex_unlock(&pdata->lock);
return 0;
}
static int msm_pcm_soft_volume_ctl_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int rc = 0;
struct snd_pcm_soft_volume *soft_vol = (struct snd_pcm_soft_volume *) snd_kcontrol_chip(kcontrol);
struct msm_plat_data *pdata = NULL;
struct snd_soc_pcm_runtime *soc_prtd = NULL;
struct snd_soc_component *component = NULL;
struct snd_pcm_substream *substream = NULL;
struct msm_audio *prtd;
if (!soft_vol || !soft_vol->pcm) {
pr_err("%s: soft vol is NULL\n", __func__);
return -ENODEV;
}
substream = soft_vol->pcm->streams[soft_vol->stream].substream;
if (!substream) {
pr_err("%s: substream not found\n", __func__);
return -ENODEV;
}
soc_prtd = substream->private_data;
if (!substream->runtime || !soc_prtd) {
pr_err("%s: substream runtime or private_data not found\n",
__func__);
return -ENODEV;
}
component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
if (!component || !component->dev) {
pr_err("%s: component is NULL\n", __func__);
return -ENODEV;
}
pdata = (struct msm_plat_data *) dev_get_drvdata(component->dev);
if (!pdata) {
pr_err("%s: pdata not found\n", __func__);
return -ENODEV;
}
mutex_lock(&pdata->lock);
if (substream->ref_count > 0) {
prtd = substream->runtime->private_data;
if ( prtd) {
if ((ucontrol->value.integer.value[0] < 0) || (ucontrol->value.integer.value[0] > 15000)) {
pr_err("%s : Ramp period range (0 to 15000), input value is out of range: %d",__func__,soft_params.period);
goto exit;
} else {
soft_params.period = ucontrol->value.integer.value[0];
}
if ((ucontrol->value.integer.value[1] < 0) || (ucontrol->value.integer.value[1] > 15000000)) {
pr_err("%s : Ramp step range (0 to 15000000), input value is out of range: %d",__func__,soft_params.step);
goto exit;
} else {
soft_params.step = ucontrol->value.integer.value[1];
}
if ((ucontrol->value.integer.value[2] < 0) || (ucontrol->value.integer.value[2] >= SOFT_VOLUME_CURVE_ENUM_MAX)) {
pr_err("%s : Ramping curve range (0 to 2), input value is out of range: %d",__func__,soft_params.rampingcurve);
goto exit;
} else {
soft_params.rampingcurve = ucontrol->value.integer.value[2];
}
pr_debug("%s : soft vol params, period: %d, step: %d, ramp curve: %d",__func__,soft_params.period,
soft_params.step,soft_params.rampingcurve);
rc = msm_pcm_set_soft_volume_params(prtd, &soft_params);
} else {
pr_err("%s: prtd not found\n", __func__);
return -ENODEV;
}
} else {
pr_err("%s: substream ref count is invalid\n", __func__);
return -ENODEV;
}
exit:
mutex_unlock(&pdata->lock);
return rc;
}
static int msm_pcm_add_soft_volume_params_control(struct snd_soc_pcm_runtime *rtd, int stream)
{
int ret = 0;
struct snd_pcm *pcm = rtd->pcm;
struct snd_pcm_soft_volume *soft_vol = NULL;
struct snd_kcontrol *kctl = NULL;
dev_dbg(rtd->dev, "%s, volume control add\n", __func__);
ret = snd_pcm_add_soft_volume_ctls(pcm, stream,
NULL,/* 1,*/ rtd->dai_link->id,
&soft_vol);
if (ret < 0) {
pr_err("%s volume control failed ret %d\n", __func__, ret);
return ret;
}
kctl = soft_vol->kctl;
kctl->put = msm_pcm_soft_volume_ctl_put;
kctl->get = msm_pcm_soft_volume_ctl_get;
return 0;
}
static void event_handler(uint32_t opcode,
uint32_t token, uint32_t *payload, void *priv)
{
@ -3497,6 +3674,16 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
pr_err("%s: Could not add pcm Volume Control %d\n",
__func__, ret);
ret = msm_pcm_add_volume_control(rtd, SNDRV_PCM_STREAM_CAPTURE);
if (ret)
pr_err("%s: Could not add pcm Volume Control %d\n",
__func__, ret);
/* adding soft vol module params mixer control command*/
ret = msm_pcm_add_soft_volume_params_control(rtd, SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
pr_err("%s: Could not add pcm Volume Control %d\n",
__func__, ret);
ret = msm_pcm_add_soft_volume_params_control(rtd, SNDRV_PCM_STREAM_CAPTURE);
if (ret)
pr_err("%s: Could not add pcm Volume Control %d\n",
__func__, ret);

View file

@ -182,6 +182,81 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx,
static void msm_routing_load_topology(size_t data_size, void *data);
static void msm_routing_unload_topology(uint32_t topology_id);
static int pcm_soft_volume_ctl_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = SOFT_VOLUME_CURVE_ENUM_MAX;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = INT_MAX;
return 0;
}
static void pcm_soft_volume_ctl_private_free(struct snd_kcontrol *kcontrol)
{
struct snd_pcm_volume *info = snd_kcontrol_chip(kcontrol);
kfree(info);
}
int snd_pcm_add_soft_volume_ctls(struct snd_pcm *pcm, int stream,
const struct snd_pcm_soft_vol_usr_elem *soft_vol_params,
unsigned long private_value,
struct snd_pcm_soft_volume **info_ret)
{
int err = 0;
int size = 0;
struct snd_pcm_soft_volume *info;
struct snd_kcontrol_new knew = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = pcm_soft_volume_ctl_info,
};
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->pcm = pcm;
info->stream = stream;
info->usr_val = soft_vol_params;
size = sizeof("Playback ") + sizeof("Soft Vol Params") +
STRING_LENGTH_OF_INT*sizeof(char) + 1;
knew.name = kzalloc(size, GFP_KERNEL);
if (!knew.name) {
kfree(info);
return -ENOMEM;
}
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
snprintf((char *)knew.name, size, "%s %d %s",
"Playback ", pcm->device, "Soft Vol Params");
else
snprintf((char *)knew.name, size, "%s %d %s",
"Capture", pcm->device, "Soft Vol Params");
knew.device = pcm->device;
knew.count = pcm->streams[stream].substream_count;
knew.private_value = private_value;
info->kctl = snd_ctl_new1(&knew, info);
if (!info->kctl) {
kfree(info);
kfree(knew.name);
return -ENOMEM;
}
info->kctl->private_free = pcm_soft_volume_ctl_private_free;
err = snd_ctl_add(pcm->card, info->kctl);
if (err < 0) {
kfree(info);
kfree(knew.name);
return -ENOMEM;
}
if (info_ret)
*info_ret = info;
kfree(knew.name);
return 0;
}
EXPORT_SYMBOL(snd_pcm_add_soft_volume_ctls);
#ifndef SND_PCM_ADD_VOLUME_CTL
static int pcm_volume_ctl_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)

20
asoc/msm-pcm-routing-v2.h Normal file → Executable file
View file

@ -800,6 +800,26 @@ int msm_pcm_routing_set_channel_mixer_runtime(
int msm_pcm_routing_set_stream_ec_ref_chmix_cfg(
int fedai_id, struct msm_pcm_channel_mixer *cfg_data);
/* array element of usr elem */
struct snd_pcm_soft_vol_usr_elem {
int val[3];
};
/* mixer control information; retrieved via snd_kcontrol_chip() */
struct snd_pcm_soft_volume {
struct snd_pcm *pcm; /* assigned PCM instance */
int stream; /* PLAYBACK or CAPTURE */
struct snd_kcontrol *kctl; /* contorl handle*/
const struct snd_pcm_soft_vol_usr_elem *usr_val;
int max_length;
void *private_data;
};
int snd_pcm_add_soft_volume_ctls(struct snd_pcm *pcm, int stream,
const struct snd_pcm_soft_vol_usr_elem *soft_vol_params,
unsigned long private_value,
struct snd_pcm_soft_volume **info_ret);
#ifndef SND_PCM_ADD_VOLUME_CTL
/* PCM Volume control API
*/

2
include/dsp/q6asm-v2.h Normal file → Executable file
View file

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2012-2019, 2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef __Q6_ASM_V2_H__
#define __Q6_ASM_V2_H__
@ -150,6 +151,7 @@ enum {
SOFT_VOLUME_CURVE_LINEAR = 0,
SOFT_VOLUME_CURVE_EXP,
SOFT_VOLUME_CURVE_LOG,
SOFT_VOLUME_CURVE_ENUM_MAX,
};
#define SOFT_VOLUME_INSTANCE_1 1