From ff271dcc374f2dfc41228feaef2f369c5151a30a Mon Sep 17 00:00:00 2001 From: Deepa Madiregama Date: Tue, 22 Apr 2014 17:06:13 +0530 Subject: ASoC: Tegra: Add compress offload volume control Add alsa control for volume changes during compress offload playback. Bug 1498475 Change-Id: I5572338648a2fefdcf3095702bcbade35f1b0565 Signed-off-by: Deepa Madiregama Reviewed-on: http://git-master/r/399682 Reviewed-by: Ravindra Lokhande GVS: Gerrit_Virtual_Submit Reviewed-by: Sumit Bhattacharya --- sound/soc/tegra/tegra_offload.c | 86 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'sound') diff --git a/sound/soc/tegra/tegra_offload.c b/sound/soc/tegra/tegra_offload.c index 465d28f8a961..3940f42c44ea 100644 --- a/sound/soc/tegra/tegra_offload.c +++ b/sound/soc/tegra/tegra_offload.c @@ -51,6 +51,8 @@ struct tegra_offload_compr_data { struct tegra_offload_compr_ops *ops; struct snd_codec codec; int stream_id; + int stream_vol[2]; + struct snd_kcontrol *kcontrol; }; static struct tegra_offload_ops offload_ops; @@ -107,6 +109,80 @@ static void tegra_offload_compr_fragment_elapsed(void *arg, unsigned int is_eos) } } +static int tegra_set_compress_volume(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = 1; + struct snd_compr_stream *stream = snd_kcontrol_chip(kcontrol); + struct tegra_offload_compr_data *data = stream->runtime->private_data; + struct snd_soc_pcm_runtime *rtd = stream->device->private_data; + struct device *dev = rtd->platform->dev; + + pr_debug("%s: value[0]: %d value[1]: %d\n", __func__, + (int)ucontrol->value.integer.value[0], + (int)ucontrol->value.integer.value[1]); + ret = data->ops->set_stream_volume(data->stream_id, + (int)ucontrol->value.integer.value[0], + (int)ucontrol->value.integer.value[1]); + if (ret < 0) { + dev_err(dev, "Failed to get compr caps. ret %d", ret); + return ret; + } else { + data->stream_vol[0] = (int)ucontrol->value.integer.value[0]; + data->stream_vol[1] = (int)ucontrol->value.integer.value[1]; + } + return 1; +} + + +static int tegra_get_compress_volume(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_compr_stream *stream = snd_kcontrol_chip(kcontrol); + struct tegra_offload_compr_data *data = stream->runtime->private_data; + + ucontrol->value.integer.value[0] = data->stream_vol[0]; + ucontrol->value.integer.value[1] = data->stream_vol[1]; + + return 0; +} + +struct snd_kcontrol_new tegra_offload_volume = + SOC_DOUBLE_EXT("Compress Playback Volume", 0, 1, 0, 0xFFFFFFFF, + 1, tegra_get_compress_volume, tegra_set_compress_volume); + +static int tegra_offload_compr_add_controls(struct snd_compr_stream *stream) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = stream->device->private_data; + struct device *dev = rtd->platform->dev; + struct tegra_offload_compr_data *data = stream->runtime->private_data; + + data->kcontrol = snd_ctl_new1(&tegra_offload_volume, stream); + ret = snd_ctl_add(rtd->card->snd_card, data->kcontrol); + if (ret < 0) { + dev_err(dev, "Can't add offload volume"); + return ret; + } + return ret; +} + + +static int tegra_offload_compr_remove_controls(struct snd_compr_stream *stream) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = stream->device->private_data; + struct device *dev = rtd->platform->dev; + struct tegra_offload_compr_data *data = stream->runtime->private_data; + + ret = snd_ctl_remove(rtd->card->snd_card, data->kcontrol); + if (ret < 0) { + dev_err(dev, "Can't remove offload volume"); + return ret; + } + return ret; +} + static int tegra_offload_compr_open(struct snd_compr_stream *stream) { struct snd_soc_pcm_runtime *rtd = stream->device->private_data; @@ -138,6 +214,11 @@ static int tegra_offload_compr_open(struct snd_compr_stream *stream) } stream->runtime->private_data = data; + + ret = tegra_offload_compr_add_controls(stream); + if (ret) + dev_err(dev, "Failed to add controls\n"); + return 0; } @@ -145,9 +226,14 @@ static int tegra_offload_compr_free(struct snd_compr_stream *stream) { struct device *dev = stream->device->dev; struct tegra_offload_compr_data *data = stream->runtime->private_data; + int ret = 0; dev_vdbg(dev, "%s", __func__); + ret = tegra_offload_compr_remove_controls(stream); + if (ret) + dev_err(dev, "Failed to remove controls\n"); + data->ops->stream_close(data->stream_id); devm_kfree(dev, data); return 0; -- cgit v1.2.3