ASoC: ops: Enforce platform maximum on initial value

Lower the volume if it is violating the platform maximum at its initial
value (i.e. at the time of the 'snd_soc_limit_volume' call).

Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
[Cherry picked from the Asahi kernel with fixups -- broonie]
Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://patch.msgid.link/20250208-asoc-volume-limit-v1-1-b98fcf4cdbad@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Martin Povišer 2025-02-08 00:57:22 +00:00 committed by Mark Brown
parent 74e0fcbd70
commit 783db6851c
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -639,6 +639,33 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
}
EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
static int snd_soc_clip_to_platform_max(struct snd_kcontrol *kctl)
{
struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
struct snd_ctl_elem_value uctl;
int ret;
if (!mc->platform_max)
return 0;
ret = kctl->get(kctl, &uctl);
if (ret < 0)
return ret;
if (uctl.value.integer.value[0] > mc->platform_max)
uctl.value.integer.value[0] = mc->platform_max;
if (snd_soc_volsw_is_stereo(mc) &&
uctl.value.integer.value[1] > mc->platform_max)
uctl.value.integer.value[1] = mc->platform_max;
ret = kctl->put(kctl, &uctl);
if (ret < 0)
return ret;
return 0;
}
/**
* snd_soc_limit_volume - Set new limit to an existing volume control.
*
@ -663,7 +690,7 @@ int snd_soc_limit_volume(struct snd_soc_card *card,
struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
if (max <= mc->max - mc->min) {
mc->platform_max = max;
ret = 0;
ret = snd_soc_clip_to_platform_max(kctl);
}
}
return ret;