Unverified Commit 249d96b4 authored by Claudiu Beznea's avatar Claudiu Beznea Committed by Mark Brown
Browse files

ASoC: da7213: Use component driver suspend/resume



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: 431e0400 ("ASoC: da7213: Add suspend to RAM support")
Signed-off-by: default avatarClaudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Link: https://patch.msgid.link/20251104114914.2060603-1-claudiu.beznea.uj@bp.renesas.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 8da0efc3
Loading
Loading
Loading
Loading
+44 −25
Original line number Diff line number Diff line
@@ -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" },
+1 −0
Original line number Diff line number Diff line
@@ -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;