ASoC: da7213: Use component driver suspend/resume

[ Upstream commit 249d96b492 ]

Since snd_soc_suspend() is invoked through snd_soc_pm_ops->suspend(),
and snd_soc_pm_ops is associated with the soc_driver (defined in
sound/soc/soc-core.c), and there is no parent-child relationship between
the soc_driver and the DA7213 codec driver, the power management subsystem
does not enforce a specific suspend/resume order between the DA7213 driver
and the soc_driver.

Because of this, the different codec component functionalities, called from
snd_soc_resume() to reconfigure various functions, can race with the
DA7213 struct dev_pm_ops::resume function, leading to misapplied
configuration. This occasionally results in clipped sound.

Fix this by dropping the struct dev_pm_ops::{suspend, resume} and use
instead struct snd_soc_component_driver::{suspend, resume}. This ensures
the proper configuration sequence is handled by the ASoC subsystem.

Cc: stable@vger.kernel.org
Fixes: 431e040065 ("ASoC: da7213: Add suspend to RAM support")
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Link: https://patch.msgid.link/20251104114914.2060603-1-claudiu.beznea.uj@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Claudiu Beznea
2025-11-20 21:04:06 -05:00
committed by Greg Kroah-Hartman
parent afd2d225a4
commit ce0138dced
2 changed files with 45 additions and 25 deletions

View File

@@ -2124,11 +2124,50 @@ static int da7213_probe(struct snd_soc_component *component)
return 0;
}
static int da7213_runtime_suspend(struct device *dev)
{
struct da7213_priv *da7213 = dev_get_drvdata(dev);
regcache_cache_only(da7213->regmap, true);
regcache_mark_dirty(da7213->regmap);
regulator_bulk_disable(DA7213_NUM_SUPPLIES, da7213->supplies);
return 0;
}
static int da7213_runtime_resume(struct device *dev)
{
struct da7213_priv *da7213 = dev_get_drvdata(dev);
int ret;
ret = regulator_bulk_enable(DA7213_NUM_SUPPLIES, da7213->supplies);
if (ret < 0)
return ret;
regcache_cache_only(da7213->regmap, false);
return regcache_sync(da7213->regmap);
}
static int da7213_suspend(struct snd_soc_component *component)
{
struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);
return da7213_runtime_suspend(da7213->dev);
}
static int da7213_resume(struct snd_soc_component *component)
{
struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);
return da7213_runtime_resume(da7213->dev);
}
static const struct snd_soc_component_driver soc_component_dev_da7213 = {
.probe = da7213_probe,
.set_bias_level = da7213_set_bias_level,
.controls = da7213_snd_controls,
.num_controls = ARRAY_SIZE(da7213_snd_controls),
.suspend = da7213_suspend,
.resume = da7213_resume,
.dapm_widgets = da7213_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(da7213_dapm_widgets),
.dapm_routes = da7213_audio_map,
@@ -2175,6 +2214,8 @@ static int da7213_i2c_probe(struct i2c_client *i2c)
if (!da7213->fin_min_rate)
return -EINVAL;
da7213->dev = &i2c->dev;
i2c_set_clientdata(i2c, da7213);
/* Get required supplies */
@@ -2224,31 +2265,9 @@ static void da7213_i2c_remove(struct i2c_client *i2c)
pm_runtime_disable(&i2c->dev);
}
static int da7213_runtime_suspend(struct device *dev)
{
struct da7213_priv *da7213 = dev_get_drvdata(dev);
regcache_cache_only(da7213->regmap, true);
regcache_mark_dirty(da7213->regmap);
regulator_bulk_disable(DA7213_NUM_SUPPLIES, da7213->supplies);
return 0;
}
static int da7213_runtime_resume(struct device *dev)
{
struct da7213_priv *da7213 = dev_get_drvdata(dev);
int ret;
ret = regulator_bulk_enable(DA7213_NUM_SUPPLIES, da7213->supplies);
if (ret < 0)
return ret;
regcache_cache_only(da7213->regmap, false);
return regcache_sync(da7213->regmap);
}
static DEFINE_RUNTIME_DEV_PM_OPS(da7213_pm, da7213_runtime_suspend,
da7213_runtime_resume, NULL);
static const struct dev_pm_ops da7213_pm = {
RUNTIME_PM_OPS(da7213_runtime_suspend, da7213_runtime_resume, NULL)
};
static const struct i2c_device_id da7213_i2c_id[] = {
{ "da7213" },

View File

@@ -595,6 +595,7 @@ enum da7213_supplies {
/* Codec private data */
struct da7213_priv {
struct regmap *regmap;
struct device *dev;
struct mutex ctrl_lock;
struct regulator_bulk_data supplies[DA7213_NUM_SUPPLIES];
struct clk *mclk;