[PATCH 12/28] ASoC: ops: Introduce 'soc_set_enum_kctl'

From: James Calligeros

Date: Sun Sep 20 2026 - 00:57:04 EST


From: Martin Povišer <povik+lin@xxxxxxxxxxx>

The new function is to be used to set enumerated controls to desired
values -- either a single control or many controls in bulk by pattern.
It is something a machine driver may call in fixup_controls.

Signed-off-by: Martin Povišer <povik+lin@xxxxxxxxxxx>
Signed-off-by: James Calligeros <jcalligeros99@xxxxxxxxx>
---
include/sound/soc.h | 2 +
sound/soc/soc-ops.c | 70 +++++++++++++++++++++++++
2 files changed, 72 insertions(+)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 973ffaf6f060..f356b553227d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -580,6 +580,8 @@ int snd_soc_limit_volume(struct snd_soc_card *card,
const char *name, int max);
int snd_soc_deactivate_kctl(struct snd_soc_card *card,
const char *name, int active);
+int snd_soc_set_enum_kctl(struct snd_soc_card *card,
+ const char *name, const char *strval);
int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index d35e24df891b..dc27d1c409ab 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -550,6 +550,76 @@ int snd_soc_deactivate_kctl(struct snd_soc_card *card,
}
EXPORT_SYMBOL_GPL(snd_soc_deactivate_kctl);

+static int soc_set_enum_kctl(struct snd_kcontrol *kctl, const char *strval)
+{
+ struct snd_ctl_elem_value value;
+ struct snd_ctl_elem_info info;
+ int sel, i, ret;
+
+ ret = kctl->info(kctl, &info);
+ if (ret < 0)
+ return ret;
+
+ if (info.type != SNDRV_CTL_ELEM_TYPE_ENUMERATED)
+ return -EINVAL;
+
+ for (sel = 0; sel < info.value.enumerated.items; sel++) {
+ info.value.enumerated.item = sel;
+ ret = kctl->info(kctl, &info);
+ if (ret < 0)
+ return ret;
+
+ if (!strcmp(strval, info.value.enumerated.name))
+ break;
+ }
+
+ if (sel == info.value.enumerated.items)
+ return -EINVAL;
+
+ for (i = 0; i < info.count; i++)
+ value.value.enumerated.item[i] = sel;
+
+ return kctl->put(kctl, &value);
+}
+
+/**
+ * snd_soc_set_enum_kctl - Set enumerated controls matching a pattern
+ *
+ * @card: where to look for the controls
+ * @name: name pattern
+ * @value: string value to set the controls to
+ *
+ * Return number of matching and set controls on success, else error.
+ * No controls need to match.
+ */
+int snd_soc_set_enum_kctl(struct snd_soc_card *card,
+ const char *name, const char *value)
+{
+ struct snd_kcontrol *kctl;
+ int hits = 0;
+ int ret;
+
+ /* Sanity check for name */
+ if (unlikely(!name))
+ return -EINVAL;
+
+ list_for_each_entry(kctl, &card->snd_card->controls, list) {
+ if (!soc_control_matches(kctl, name))
+ continue;
+
+ ret = soc_set_enum_kctl(kctl, value);
+ if (ret < 0)
+ return ret;
+ hits++;
+ }
+
+ if (!hits)
+ return -EINVAL;
+
+ return hits;
+}
+EXPORT_SYMBOL_GPL(snd_soc_set_enum_kctl);
+
int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{

--
2.55.0