91 lines
3.2 KiB
Diff
91 lines
3.2 KiB
Diff
From 29408c08047402839d40cb03bf870efcf476c361 Mon Sep 17 00:00:00 2001
|
|
From: Charles Keepax <ckeepax@opensource.cirrus.com>
|
|
Date: Wed, 4 Feb 2026 12:59:43 +0000
|
|
Subject: [PATCH 14/17] ASoC: SDCA: Limit values user can write to Selected
|
|
Mode
|
|
|
|
Prevent the user from both updating the Selected Mode control
|
|
whilst the jack is not present, and from writing values that don't
|
|
correspond to a valid jack type (Unknown, in progress, etc.).
|
|
|
|
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
|
|
Link: https://patch.msgid.link/20260204125944.1134011-7-ckeepax@opensource.cirrus.com
|
|
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
|
|
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
---
|
|
sound/soc/sdca/sdca_asoc.c | 37 ++++++++++++++++++++++++++++++++++++-
|
|
sound/soc/sdca/sdca_jack.c | 2 +-
|
|
2 files changed, 37 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c
|
|
index 9685281529e9..bb6e74e80a3e 100644
|
|
--- a/sound/soc/sdca/sdca_asoc.c
|
|
+++ b/sound/soc/sdca/sdca_asoc.c
|
|
@@ -116,6 +116,41 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun
|
|
}
|
|
EXPORT_SYMBOL_NS(sdca_asoc_count_component, "SND_SOC_SDCA");
|
|
|
|
+static int ge_put_enum_double(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
|
|
+ struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
|
|
+ struct device *dev = component->dev;
|
|
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
|
+ unsigned int *item = ucontrol->value.enumerated.item;
|
|
+ unsigned int reg = e->reg;
|
|
+ int ret;
|
|
+
|
|
+ reg &= ~SDW_SDCA_CTL_CSEL(0x3F);
|
|
+ reg |= SDW_SDCA_CTL_CSEL(SDCA_CTL_GE_DETECTED_MODE);
|
|
+
|
|
+ ret = pm_runtime_resume_and_get(dev);
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "failed to resume writing %s: %d\n",
|
|
+ kcontrol->id.name, ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = snd_soc_component_read(component, reg);
|
|
+ pm_runtime_put(dev);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ else if (ret <= SDCA_DETECTED_MODE_DETECTION_IN_PROGRESS)
|
|
+ return -EBUSY;
|
|
+
|
|
+ ret = snd_soc_enum_item_to_val(e, item[0]);
|
|
+ if (ret <= SDCA_DETECTED_MODE_DETECTION_IN_PROGRESS)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
|
|
+}
|
|
+
|
|
static int entity_early_parse_ge(struct device *dev,
|
|
struct sdca_function_data *function,
|
|
struct sdca_entity *entity)
|
|
@@ -192,7 +227,7 @@ static int entity_early_parse_ge(struct device *dev,
|
|
kctl->name = control_name;
|
|
kctl->info = snd_soc_info_enum_double;
|
|
kctl->get = snd_soc_dapm_get_enum_double;
|
|
- kctl->put = snd_soc_dapm_put_enum_double;
|
|
+ kctl->put = ge_put_enum_double;
|
|
kctl->private_value = (unsigned long)soc_enum;
|
|
|
|
entity->ge.kctl = kctl;
|
|
diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c
|
|
index bfa621b744e1..605514f02045 100644
|
|
--- a/sound/soc/sdca/sdca_jack.c
|
|
+++ b/sound/soc/sdca/sdca_jack.c
|
|
@@ -105,7 +105,7 @@ int sdca_jack_process(struct sdca_interrupt *interrupt)
|
|
|
|
ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(soc_enum, val);
|
|
|
|
- ret = kctl->put(kctl, ucontrol);
|
|
+ ret = snd_soc_dapm_put_enum_double(kctl, ucontrol);
|
|
if (ret < 0) {
|
|
dev_err(dev, "failed to update selected mode: %d\n", ret);
|
|
return ret;
|
|
--
|
|
2.43.0
|
|
|