[PATCH 01/20] ASoC: adau1372: Unwind failed power restoration

Pengpeng Hou <[email protected]>
Newsgroups gmane.linux.sound,gmane.linux.kernel
Message-ID <[email protected]>
adau1372_set_power() enables MCLK and optional PLL state before
restoring the clock-control register and register cache.  The final two
operations are unchecked, so the DAPM bias callback can report STANDBY
while hardware restoration is incomplete.

Check the clock-control update and cache replay.  Reuse one failure path
for PLL, register and cache errors that powers the device back down,
restores cache-only and dirty state, and disables MCLK.

The issue was identified via static analysis and manually reviewed.

Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")

Assisted-by: LLM
Signed-off-by: Pengpeng Hou <[email protected]>
---
 sound/soc/codecs/adau1372.c | 44 +++++++++++++++++++++++--------------
 1 file changed, 28 insertions(+), 16 deletions(-)

diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
index cc174ec3a1f8..6a4decd66d93 100644
--- a/sound/soc/codecs/adau1372.c
+++ b/sound/soc/codecs/adau1372.c
@@ -787,12 +787,13 @@ static int adau1372_enable_pll(struct adau1372 *adau1372)
 
 static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
 {
+	int ret;
+
 	if (adau1372->enabled == enable)
 		return 0;
 
 	if (enable) {
 		unsigned int clk_ctrl = ADAU1372_CLK_CTRL_MCLK_EN;
-		int ret;
 
 		ret = clk_prepare_enable(adau1372->mclk);
 		if (ret)
@@ -811,24 +812,21 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
 		 */
 		if (adau1372->use_pll) {
 			ret = adau1372_enable_pll(adau1372);
-			if (ret) {
-				if (!adau1372->pd_gpio)
-					regmap_update_bits(adau1372->regmap,
-							   ADAU1372_REG_CLK_CTRL,
-							   ADAU1372_CLK_CTRL_PLL_EN,
-							   0);
-				regcache_cache_only(adau1372->regmap, true);
-				if (adau1372->pd_gpio)
-					gpiod_set_value(adau1372->pd_gpio, 1);
-				clk_disable_unprepare(adau1372->mclk);
-				return ret;
-			}
+			if (ret)
+				goto err_power_down;
 			clk_ctrl |= ADAU1372_CLK_CTRL_CLKSRC;
 		}
 
-		regmap_update_bits(adau1372->regmap, ADAU1372_REG_CLK_CTRL,
-				   ADAU1372_CLK_CTRL_MCLK_EN | ADAU1372_CLK_CTRL_CLKSRC, clk_ctrl);
-		regcache_sync(adau1372->regmap);
+		ret = regmap_update_bits(adau1372->regmap, ADAU1372_REG_CLK_CTRL,
+					 ADAU1372_CLK_CTRL_MCLK_EN |
+					 ADAU1372_CLK_CTRL_CLKSRC,
+					 clk_ctrl);
+		if (ret)
+			goto err_power_down;
+
+		ret = regcache_sync(adau1372->regmap);
+		if (ret)
+			goto err_power_down;
 	} else {
 		if (adau1372->pd_gpio) {
 			/*
@@ -849,6 +847,20 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
 	adau1372->enabled = enable;
 
 	return 0;
+
+err_power_down:
+	if (!adau1372->pd_gpio)
+		regmap_update_bits(adau1372->regmap, ADAU1372_REG_CLK_CTRL,
+				   ADAU1372_CLK_CTRL_MCLK_EN |
+				   ADAU1372_CLK_CTRL_PLL_EN, 0);
+
+	regcache_cache_only(adau1372->regmap, true);
+	regcache_mark_dirty(adau1372->regmap);
+	if (adau1372->pd_gpio)
+		gpiod_set_value(adau1372->pd_gpio, 1);
+	clk_disable_unprepare(adau1372->mclk);
+
+	return ret;
 }
 
 static int adau1372_set_bias_level(struct snd_soc_component *component,
-- 
2.43.0
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.