mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-23 00:55:48 -04:00
ASoC: SDCA: Handle volatile controls correctly
There are very few volatile controls in SDCA that are exported
as ALSA controls, typically Detected Mode is the only common
one. However, the current code does not resume the device when
these ALSA controls are accessed, which will result in the
read/write failing.
Add a new wrapper specifically for volatile controls that will do
the required pm_runtime operations before accessing the register.
Fixes: c3ca24e3fc ("ASoC: SDCA: Create ALSA controls from DisCo")
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://patch.msgid.link/20260204125944.1134011-3-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:
committed by
Mark Brown
parent
b27b57f85f
commit
9fad74b79e
@@ -16,6 +16,7 @@
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/soundwire/sdw_registers.h>
|
||||
#include <linux/string_helpers.h>
|
||||
@@ -792,6 +793,48 @@ static int control_limit_kctl(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int volatile_get_volsw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct device *dev = component->dev;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to resume reading %s: %d\n",
|
||||
kcontrol->id.name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_get_volsw(kcontrol, ucontrol);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int volatile_put_volsw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct device *dev = component->dev;
|
||||
int ret;
|
||||
|
||||
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_put_volsw(kcontrol, ucontrol);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int populate_control(struct device *dev,
|
||||
struct sdca_function_data *function,
|
||||
struct sdca_entity *entity,
|
||||
@@ -849,8 +892,13 @@ static int populate_control(struct device *dev,
|
||||
(*kctl)->private_value = (unsigned long)mc;
|
||||
(*kctl)->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
(*kctl)->info = snd_soc_info_volsw;
|
||||
(*kctl)->get = snd_soc_get_volsw;
|
||||
(*kctl)->put = snd_soc_put_volsw;
|
||||
if (control->is_volatile) {
|
||||
(*kctl)->get = volatile_get_volsw;
|
||||
(*kctl)->put = volatile_put_volsw;
|
||||
} else {
|
||||
(*kctl)->get = snd_soc_get_volsw;
|
||||
(*kctl)->put = snd_soc_put_volsw;
|
||||
}
|
||||
|
||||
if (readonly_control(control))
|
||||
(*kctl)->access = SNDRV_CTL_ELEM_ACCESS_READ;
|
||||
|
||||
Reference in New Issue
Block a user