[PATCH 04/20] ASoC: cs42l42: Propagate system resume restore errors
From: Pengpeng Hou
Date: Fri Aug 28 2026 - 07:35:30 EST
Commit a118fea777a2 ("ASoC: codecs: cs42l42-sdw: Propagate
regcache_sync() errors") makes the SoundWire runtime-resume path return
failures from the LATCH_TO_VP and full cache replay. The separate
shared system-resume restore helper still ignores the same two
operations and clears suspended. Both the I2C and SoundWire
system-resume callbacks call this helper.
Make cs42l42_resume_restore() return the first replay error. Keep
suspended set and restore reset, cache-only state and supplies before
returning the error through both bus callbacks.
The issue was identified via static analysis and manually reviewed.
Fixes: f8593e885400 ("ASoC: cs42l42: Handle system suspend")
Assisted-by: LLM
Signed-off-by: Pengpeng Hou <pengpeng@xxxxxxxxxxx>
---
sound/soc/codecs/cs42l42-sdw.c | 4 +---
sound/soc/codecs/cs42l42.c | 27 ++++++++++++++++++++-------
sound/soc/codecs/cs42l42.h | 2 +-
3 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/sound/soc/codecs/cs42l42-sdw.c b/sound/soc/codecs/cs42l42-sdw.c
index b61ca74dcf0b..055c37c08e87 100644
--- a/sound/soc/codecs/cs42l42-sdw.c
+++ b/sound/soc/codecs/cs42l42-sdw.c
@@ -514,9 +514,7 @@ static int cs42l42_sdw_resume(struct device *dev)
if (ret < 0)
return ret;
- cs42l42_resume_restore(dev);
-
- return 0;
+ return cs42l42_resume_restore(dev);
}
static int cs42l42_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id)
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index fadf68860601..b6e9b7f53977 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -2237,22 +2237,37 @@ int cs42l42_resume(struct device *dev)
}
EXPORT_SYMBOL_NS_GPL(cs42l42_resume, "SND_SOC_CS42L42_CORE");
-void cs42l42_resume_restore(struct device *dev)
+int cs42l42_resume_restore(struct device *dev)
{
struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
+ int ret;
regcache_cache_only(cs42l42->regmap, false);
regcache_mark_dirty(cs42l42->regmap);
scoped_guard(mutex, &cs42l42->irq_lock) {
/* Sync LATCH_TO_VP first so the VP domain registers sync correctly */
- regcache_sync_region(cs42l42->regmap, CS42L42_MIC_DET_CTL1, CS42L42_MIC_DET_CTL1);
- regcache_sync(cs42l42->regmap);
+ ret = regcache_sync_region(cs42l42->regmap,
+ CS42L42_MIC_DET_CTL1,
+ CS42L42_MIC_DET_CTL1);
+ if (!ret)
+ ret = regcache_sync(cs42l42->regmap);
+
+ if (!ret)
+ cs42l42->suspended = false;
+ }
- cs42l42->suspended = false;
+ if (ret) {
+ regcache_cache_only(cs42l42->regmap, true);
+ gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
+ regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies),
+ cs42l42->supplies);
+ return ret;
}
dev_dbg(dev, "System resumed\n");
+
+ return 0;
}
EXPORT_SYMBOL_NS_GPL(cs42l42_resume_restore, "SND_SOC_CS42L42_CORE");
@@ -2264,9 +2279,7 @@ static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
if (ret)
return ret;
- cs42l42_resume_restore(dev);
-
- return 0;
+ return cs42l42_resume_restore(dev);
}
int cs42l42_common_probe(struct cs42l42_private *cs42l42,
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index 3d85ebc59489..7f17b9f73be6 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -72,7 +72,7 @@ int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream);
irqreturn_t cs42l42_irq_thread(int irq, void *data);
int cs42l42_suspend(struct device *dev);
int cs42l42_resume(struct device *dev);
-void cs42l42_resume_restore(struct device *dev);
+int cs42l42_resume_restore(struct device *dev);
int cs42l42_common_probe(struct cs42l42_private *cs42l42,
const struct snd_soc_component_driver *component_drv,
struct snd_soc_dai_driver *dai);
--
2.43.0