]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: ops: Enforce platform maximum on initial value
authorMartin Povišer <povik+lin@cutebit.org>
Sat, 8 Feb 2025 00:57:22 +0000 (00:57 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 17 Feb 2025 12:09:38 +0000 (12:09 +0000)
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>
sound/soc/soc-ops.c

index c6601ef16f843b96fa23cbb473a3d0a006e72c21..a7d0d4035d65eb546544dd7c4b28912f4410808c 100644 (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;