[PATCH 1/2] ASoC: codecs: sn624x: enable runtime PM on first attach

Qianghua Wang <[email protected]>
Newsgroups gmane.linux.sound
Message-ID <[email protected]>
Runtime PM was enabled unconditionally from probe after
register_component(). set_jack() can run in that window and
touch RPM before it is enabled, leading to mismatched get/put
counts. remove() only called pm_runtime_disable() when
first_hw_init was set, which did not match the probe enable.

Enable runtime PM from io_init() on first ATTACHED instead,
and do not use runtime PM from set_jack() until then. If
set_jack() ran early, take the long-lived jack PM reference
once io_init() has enabled RPM.

Signed-off-by: Qianghua Wang <[email protected]>
---
 sound/soc/codecs/sn624x-sdca-sdw.c | 63 ++++++++++++++++++++----------
 1 file changed, 43 insertions(+), 20 deletions(-)

diff --git a/sound/soc/codecs/sn624x-sdca-sdw.c b/sound/soc/codecs/sn624x-sdca-sdw.c
index cd18936037e9..8fd37f18fe5e 100644
--- a/sound/soc/codecs/sn624x-sdca-sdw.c
+++ b/sound/soc/codecs/sn624x-sdca-sdw.c
@@ -869,12 +869,16 @@ static int sn624x_jack_rpm_get(struct sn624x_sdca_priv *sn624x)
 
 	dev = sn624x->component->dev;
 	ret = pm_runtime_resume_and_get(dev);
-	if (ret < 0 && ret != -EACCES) {
-		dev_err(dev, "sn624x: jack rpm get failed (%d)\n", ret);
-		return ret;
+	if (ret < 0) {
+		if (ret != -EACCES) {
+			dev_err(dev, "sn624x: jack rpm get failed (%d)\n", ret);
+			return ret;
+		}
+		/* pm_runtime not enabled yet (before first ATTACHED io_init) */
+		return 0;
 	}
-	if (ret >= 0)
-		sn624x->jack_rpm = true;
+
+	sn624x->jack_rpm = true;
 	return 0;
 }
 
@@ -988,6 +992,18 @@ static int sn624x_sdca_set_jack_detect(struct snd_soc_component *component,
 		return 0;
 	}
 
+	/*
+	 * Component registration happens before runtime PM is enabled (RPM is
+	 * enabled from io_init on first ATTACHED). Do not touch runtime PM
+	 * until then, or get/put counts can go out of sync.
+	 */
+	if (!sn624x->first_hw_init) {
+		sn624x->hs_jack = hs_jack;
+		sn624x->jack_type_last = -1;
+		sn624x_jack_schedule_poll(sn624x);
+		return 0;
+	}
+
 	/*
 	 * Take the runtime PM reference before publishing hs_jack, so a
 	 * failed get cannot leave jack detection marked as enabled.
@@ -998,13 +1014,6 @@ static int sn624x_sdca_set_jack_detect(struct snd_soc_component *component,
 
 	sn624x->hs_jack = hs_jack;
 	sn624x->jack_type_last = -1;
-
-	/* set_jack may run before io_init; poll waits until hw_init. */
-	if (!sn624x->first_hw_init) {
-		sn624x_jack_schedule_poll(sn624x);
-		return 0;
-	}
-
 	sn624x_sdca_jack_init(sn624x);
 	return 0;
 }
@@ -1122,13 +1131,30 @@ static int sn624x_sdca_io_init(struct device *dev, struct sdw_slave *slave)
 	sn624x_sdca_sdca_irq_mask_all(sn624x);
 
 	regcache_cache_only(sn624x->regmap, false);
+	if (!sn624x->first_hw_init) {
+		/*
+		 * PM runtime is only enabled when a Slave reports as Attached
+		 * (same pattern as rt722).
+		 */
+		pm_runtime_set_autosuspend_delay(dev, 3000);
+		pm_runtime_use_autosuspend(dev);
+		pm_runtime_set_active(dev);
+		pm_runtime_mark_last_busy(dev);
+		pm_runtime_enable(dev);
+	}
 
 	pm_runtime_get_noresume(dev);
 
 	sn624x_uaj_apply_io_defaults(sn624x);
 
-	if (sn624x->hs_jack)
+	/*
+	 * set_jack() may have run before RPM was enabled (-EACCES). Take the
+	 * long-lived jack PM ref now that runtime PM is active.
+	 */
+	if (sn624x->hs_jack) {
+		sn624x_jack_rpm_get(sn624x);
 		sn624x_sdca_jack_init(sn624x);
+	}
 
 	ret = sn624x_sdca_jack_function_init(dev, sn624x);
 	if (ret < 0) {
@@ -1149,8 +1175,6 @@ static int sn624x_sdca_io_init(struct device *dev, struct sdw_slave *slave)
 	if (sn624x->first_hw_init)
 		regcache_mark_dirty(sn624x->regmap);
 
-	pm_runtime_set_active(dev);
-
 	sn624x->hw_init = true;
 	sn624x->first_hw_init = true;
 
@@ -1692,11 +1716,10 @@ int sn624x_sdca_init(struct device *dev, struct regmap *regmap,
 	if (ret < 0)
 		return ret;
 
-	pm_runtime_set_autosuspend_delay(dev, 3000);
-	pm_runtime_use_autosuspend(dev);
-	pm_runtime_mark_last_busy(dev);
-	pm_runtime_enable(dev);
-
+	/*
+	 * Do not enable runtime PM here. SoundWire slaves are only powered /
+	 * accessible after ATTACHED; enable RPM from io_init() then.
+	 */
 	SN624X_DBG(dev, "snd_soc_register_component OK (DAI sn624x-sdca-aif)\n");
 	return 0;
 }
-- 
2.47.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.