[L/Unstable] [PATCH 09/16] ALSA: hda: cs35l41: Ensure we correctly re-sync regmap before system suspending.
Kai-Heng Feng
kai.heng.feng at canonical.com
Tue Aug 1 08:36:42 UTC 2023
From: Stefan Binding <sbinding at opensource.cirrus.com>
BugLink: https://bugs.launchpad.net/bugs/2029199
In order to properly system suspend, it is necessary to unload the firmware
and ensure the chip is ready for shutdown (if necessary). If the system
is currently in runtime suspend, it is necessary to wake up the device,
and then make it ready. Currently, the wake does not correctly resync
the device, which may mean it cannot suspend correctly. Fix this by
performaing a resync.
Signed-off-by: Stefan Binding <sbinding at opensource.cirrus.com>
Link: https://lore.kernel.org/r/20230721151816.2080453-5-sbinding@opensource.cirrus.com
Signed-off-by: Takashi Iwai <tiwai at suse.de>
(cherry picked from commit a3ff564658783e3cd9cc3098da4aebd89fe07d74 linux-next)
Signed-off-by: Kai-Heng Feng <kai.heng.feng at canonical.com>
---
sound/pci/hda/cs35l41_hda.c | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index d7cd8ad2d555..eb6710ecb166 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -574,21 +574,43 @@ static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsi
rx_slot);
}
-static void cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)
+static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)
{
+ int ret = 0;
+
mutex_lock(&cs35l41->fw_mutex);
if (cs35l41->firmware_running) {
regcache_cache_only(cs35l41->regmap, false);
- cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap);
+ ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap);
+ if (ret) {
+ dev_warn(cs35l41->dev, "Unable to exit Hibernate.");
+ goto err;
+ }
+
+ /* Test key needs to be unlocked to allow the OTP settings to re-apply */
+ cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
+ ret = regcache_sync(cs35l41->regmap);
+ cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);
+ if (ret) {
+ dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret);
+ goto err;
+ }
+
+ if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
+ cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);
+
cs35l41_shutdown_dsp(cs35l41);
cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
-
- regcache_cache_only(cs35l41->regmap, true);
- regcache_mark_dirty(cs35l41->regmap);
}
+err:
+ regcache_cache_only(cs35l41->regmap, true);
+ regcache_mark_dirty(cs35l41->regmap);
+
mutex_unlock(&cs35l41->fw_mutex);
+
+ return ret;
}
static int cs35l41_system_suspend(struct device *dev)
--
2.34.1
More information about the kernel-team
mailing list