[alsa-devel] [PATCH] ASoC: core: Support for limiting the volume
Add support for the core to limit the maximum volume on an existing control. The function will modify the soc_mixer_control.max value of the given control. The new value must be lower than the original one (chip maximum)
If there is a need for limiting a gain on a given control, than machine drivers can do the following in their snd_soc_dai_link.init function:
snd_soc_limit_volume(codec, "TPA6140A2 Headphone Playback Volume", 21);
This will modify the original 31 (chip maximum) to 21, so user space will not be able to set the gain higher than this.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@nokia.com --- include/sound/soc.h | 2 ++ sound/soc/soc-core.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 01e9c66..9f306f0 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -326,6 +326,8 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int snd_soc_limit_volume(struct snd_soc_codec *codec, + const char *name, int max);
/** * struct snd_soc_jack_pin - Describes a pin to update based on jack detection diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d59076e..4079223 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2238,6 +2238,45 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
/** + * snd_soc_limit_volume - Set new limit to an existing volume control. + * + * @codec: where to look for the control + * @name: Name of the control + * @max: new maximum limit + * + * Return 0 for success, else error. + */ +int snd_soc_limit_volume(struct snd_soc_codec *codec, + const char *name, int max) +{ + struct snd_card *card = codec->card; + struct snd_kcontrol *kctl; + struct soc_mixer_control *mc; + int found = 0; + int ret = -EINVAL; + + /* Sanity check for name and max */ + if (unlikely(!name || max <= 0)) + return -EINVAL; + + list_for_each_entry(kctl, &card->controls, list) { + if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) { + found = 1; + break; + } + } + if (found) { + mc = (struct soc_mixer_control *)kctl->private_value; + if (max <= mc->max) { + mc->max = max; + ret = 0; + } + } + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_limit_volume); + +/** * snd_soc_dai_set_sysclk - configure DAI system or master clock. * @dai: DAI * @clk_id: DAI specific clock ID
On Fri, 2010-05-07 at 14:05 +0300, Peter Ujfalusi wrote:
Add support for the core to limit the maximum volume on an existing control. The function will modify the soc_mixer_control.max value of the given control. The new value must be lower than the original one (chip maximum)
If there is a need for limiting a gain on a given control, than machine drivers can do the following in their snd_soc_dai_link.init function:
snd_soc_limit_volume(codec, "TPA6140A2 Headphone Playback Volume", 21);
This will modify the original 31 (chip maximum) to 21, so user space will not be able to set the gain higher than this.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@nokia.com
Acked-by: Liam Girdwood lrg@slimlogic.co.uk
On Fri, May 07, 2010 at 02:05:49PM +0300, Peter Ujfalusi wrote:
Add support for the core to limit the maximum volume on an existing control. The function will modify the soc_mixer_control.max value of the given control. The new value must be lower than the original one (chip maximum)
Applied, thanks.
On Friday 07 May 2010 18:41:20 ext Mark Brown wrote:
On Fri, May 07, 2010 at 02:05:49PM +0300, Peter Ujfalusi wrote:
Add support for the core to limit the maximum volume on an existing control. The function will modify the soc_mixer_control.max value of the given control. The new value must be lower than the original one (chip maximum)
Applied, thanks.
Thanks, however it seams that if the control has invert enabled this is going to break. In case of invert we need to invert from the chip maximum, and not from the platform dependent limit. The only way I can think of to solve this is to introduce new variable in soc_mixer_control struct. It can be called platform_max. The snd_soc_limit_volume would modify the platform_max leaving the max as configured by the drivers (chip maximum). In volsw_info calls than we return the platform_max instead of max. If in the _info call the platform_max is 0, than we take the max to report (some custom kcontrol macro might not aware of the change in codec drivers).
What do you think?
On Mon, May 10, 2010 at 10:07:58AM +0300, Peter Ujfalusi wrote:
however it seams that if the control has invert enabled this is going to break. In case of invert we need to invert from the chip maximum, and not from the platform dependent limit. The only way I can think of to solve this is to introduce new variable in soc_mixer_control struct. It can be called platform_max. The snd_soc_limit_volume would modify the platform_max leaving the max as configured by the drivers (chip maximum). In volsw_info calls than we return the platform_max instead of max. If in the _info call the platform_max is 0, than we take the max to report (some custom kcontrol macro might not aware of the change in codec drivers).
What do you think?
That sounds sensible enough.
participants (3)
-
Liam Girdwood
-
Mark Brown
-
Peter Ujfalusi