Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91c55669 authored by Krishna Kishor Jha's avatar Krishna Kishor Jha Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarKrishna Kishor Jha <quic_kkishorj@quicinc.com>
parent dd9977f0
Loading
Loading
Loading
Loading

asoc/msm-pcm-q6-v2.c

100644 → 100755
+187 −0
Original line number Diff line number Diff line
@@ -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);
+75 −0
Original line number Diff line number Diff line
@@ -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)

asoc/msm-pcm-routing-v2.h

100644 → 100755
+20 −0
Original line number Diff line number Diff line
@@ -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
 */

include/dsp/q6asm-v2.h

100644 → 100755
+2 −0
Original line number Diff line number Diff line
/* 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