mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
ASoC: da7213: Use component driver suspend/resume
[ Upstream commit249d96b492] 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:
committed by
Greg Kroah-Hartman
parent
afd2d225a4
commit
ce0138dced
@@ -2124,11 +2124,50 @@ static int da7213_probe(struct snd_soc_component *component)
|
|||||||
return 0;
|
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 = {
|
static const struct snd_soc_component_driver soc_component_dev_da7213 = {
|
||||||
.probe = da7213_probe,
|
.probe = da7213_probe,
|
||||||
.set_bias_level = da7213_set_bias_level,
|
.set_bias_level = da7213_set_bias_level,
|
||||||
.controls = da7213_snd_controls,
|
.controls = da7213_snd_controls,
|
||||||
.num_controls = ARRAY_SIZE(da7213_snd_controls),
|
.num_controls = ARRAY_SIZE(da7213_snd_controls),
|
||||||
|
.suspend = da7213_suspend,
|
||||||
|
.resume = da7213_resume,
|
||||||
.dapm_widgets = da7213_dapm_widgets,
|
.dapm_widgets = da7213_dapm_widgets,
|
||||||
.num_dapm_widgets = ARRAY_SIZE(da7213_dapm_widgets),
|
.num_dapm_widgets = ARRAY_SIZE(da7213_dapm_widgets),
|
||||||
.dapm_routes = da7213_audio_map,
|
.dapm_routes = da7213_audio_map,
|
||||||
@@ -2175,6 +2214,8 @@ static int da7213_i2c_probe(struct i2c_client *i2c)
|
|||||||
if (!da7213->fin_min_rate)
|
if (!da7213->fin_min_rate)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
da7213->dev = &i2c->dev;
|
||||||
|
|
||||||
i2c_set_clientdata(i2c, da7213);
|
i2c_set_clientdata(i2c, da7213);
|
||||||
|
|
||||||
/* Get required supplies */
|
/* Get required supplies */
|
||||||
@@ -2224,31 +2265,9 @@ static void da7213_i2c_remove(struct i2c_client *i2c)
|
|||||||
pm_runtime_disable(&i2c->dev);
|
pm_runtime_disable(&i2c->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int da7213_runtime_suspend(struct device *dev)
|
static const struct dev_pm_ops da7213_pm = {
|
||||||
{
|
RUNTIME_PM_OPS(da7213_runtime_suspend, da7213_runtime_resume, NULL)
|
||||||
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 i2c_device_id da7213_i2c_id[] = {
|
static const struct i2c_device_id da7213_i2c_id[] = {
|
||||||
{ "da7213" },
|
{ "da7213" },
|
||||||
|
|||||||
@@ -595,6 +595,7 @@ enum da7213_supplies {
|
|||||||
/* Codec private data */
|
/* Codec private data */
|
||||||
struct da7213_priv {
|
struct da7213_priv {
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
|
struct device *dev;
|
||||||
struct mutex ctrl_lock;
|
struct mutex ctrl_lock;
|
||||||
struct regulator_bulk_data supplies[DA7213_NUM_SUPPLIES];
|
struct regulator_bulk_data supplies[DA7213_NUM_SUPPLIES];
|
||||||
struct clk *mclk;
|
struct clk *mclk;
|
||||||
|
|||||||
Reference in New Issue
Block a user