Skip to content

Commit d0d4aee

Browse files
Stefan Bindingsmb49
authored andcommitted
ALSA: hda: cs35l41: Ensure we correctly re-sync regmap before system suspending.
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@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230721151816.2080453-5-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai <tiwai@suse.de> (cherry picked from commit a3ff564658783e3cd9cc3098da4aebd89fe07d74 linux-next) Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
1 parent 988af66 commit d0d4aee

1 file changed

Lines changed: 27 additions & 5 deletions

File tree

sound/pci/hda/cs35l41_hda.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -574,21 +574,43 @@ static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsi
574574
rx_slot);
575575
}
576576

577-
static void cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)
577+
static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)
578578
{
579+
int ret = 0;
580+
579581
mutex_lock(&cs35l41->fw_mutex);
580582
if (cs35l41->firmware_running) {
581583

582584
regcache_cache_only(cs35l41->regmap, false);
583585

584-
cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap);
586+
ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap);
587+
if (ret) {
588+
dev_warn(cs35l41->dev, "Unable to exit Hibernate.");
589+
goto err;
590+
}
591+
592+
/* Test key needs to be unlocked to allow the OTP settings to re-apply */
593+
cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
594+
ret = regcache_sync(cs35l41->regmap);
595+
cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);
596+
if (ret) {
597+
dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret);
598+
goto err;
599+
}
600+
601+
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
602+
cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);
603+
585604
cs35l41_shutdown_dsp(cs35l41);
586605
cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
587-
588-
regcache_cache_only(cs35l41->regmap, true);
589-
regcache_mark_dirty(cs35l41->regmap);
590606
}
607+
err:
608+
regcache_cache_only(cs35l41->regmap, true);
609+
regcache_mark_dirty(cs35l41->regmap);
610+
591611
mutex_unlock(&cs35l41->fw_mutex);
612+
613+
return ret;
592614
}
593615

594616
static int cs35l41_system_suspend(struct device *dev)

0 commit comments

Comments
 (0)