Commit 637d3847 authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown
Browse files

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: default avatarPeter Ujfalusi <peter.ujfalusi@nokia.com>
Acked-by: default avatarLiam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 30578764
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
+39 −0
Original line number Diff line number Diff line
@@ -2237,6 +2237,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