]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ASoC: da7213: Use component driver suspend/resume
authorClaudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Tue, 4 Nov 2025 11:49:14 +0000 (13:49 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 4 Nov 2025 13:53:26 +0000 (13:53 +0000)
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: 431e040065c8 ("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>
sound/soc/codecs/da7213.c
sound/soc/codecs/da7213.h

index ae89260ca215ffbbf391c35fc52d468d2e29eb60..3420011da444ce43f7f98cedd8c93235c58d14f4 100644 (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" },
index b9ab791d6b883b1baaa65e35e99284821435b353..29cbf0eb612438cecfb585f74401f4a0189ac5af 100644 (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;