mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 10:33:41 +02:00
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>
This commit is contained in:
parent
02d851b46b
commit
812ff1baa7
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user