Skip to content

Commit ffbefd0

Browse files
Stefan Bindingsmb49
authored andcommitted
ALSA: hda: cs35l41: Rework System Suspend to ensure correct call separation
BugLink: https://bugs.launchpad.net/bugs/2029199 In order to correctly pause audio on suspend, amps using external boost require parts of the pause sequence to be called for all amps before moving on to the next steps. For example, as part of pausing the audio, the VSPK GPIO must be disabled, but since this GPIO is controlled by one amp, but controls the boost for all amps, it is required to separate the calls. During playback this is achieved by using the pre and post playback hooks, however during system suspend, this is not possible, so to separate the calls, we use both the .prepare and .suspend calls to pause the audio. Currently, for this reason, we do not restart audio on system resume. However, we can support this by relying on the playback hook to resume playback after system suspend. Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230721151816.2080453-10-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai <tiwai@suse.de> (cherry picked from commit c4d0510b81c430249ee69c0554bb7ce4fa3d539e linux-next) Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
1 parent c6b3cd3 commit ffbefd0

1 file changed

Lines changed: 35 additions & 5 deletions

File tree

sound/pci/hda/cs35l41_hda.c

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,15 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action)
595595
mutex_unlock(&cs35l41->fw_mutex);
596596
break;
597597
case HDA_GEN_PCM_ACT_CLOSE:
598+
mutex_lock(&cs35l41->fw_mutex);
599+
if (!cs35l41->firmware_running && cs35l41->request_fw_load &&
600+
!cs35l41->fw_request_ongoing) {
601+
dev_info(dev, "Requesting Firmware Load after HDA_GEN_PCM_ACT_CLOSE\n");
602+
cs35l41->fw_request_ongoing = true;
603+
schedule_work(&cs35l41->fw_load_work);
604+
}
605+
mutex_unlock(&cs35l41->fw_mutex);
606+
598607
/*
599608
* Playback must be finished for all amps before we start runtime suspend.
600609
* This ensures no amps are playing back when we start putting them to sleep.
@@ -681,6 +690,25 @@ static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)
681690
return ret;
682691
}
683692

693+
static int cs35l41_system_suspend_prep(struct device *dev)
694+
{
695+
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
696+
697+
dev_dbg(cs35l41->dev, "System Suspend Prepare\n");
698+
699+
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {
700+
dev_err_once(cs35l41->dev, "System Suspend not supported\n");
701+
return 0; /* don't block the whole system suspend */
702+
}
703+
704+
mutex_lock(&cs35l41->fw_mutex);
705+
if (cs35l41->playback_started)
706+
cs35l41_hda_pause_start(dev);
707+
mutex_unlock(&cs35l41->fw_mutex);
708+
709+
return 0;
710+
}
711+
684712
static int cs35l41_system_suspend(struct device *dev)
685713
{
686714
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
@@ -693,6 +721,11 @@ static int cs35l41_system_suspend(struct device *dev)
693721
return 0; /* don't block the whole system suspend */
694722
}
695723

724+
mutex_lock(&cs35l41->fw_mutex);
725+
if (cs35l41->playback_started)
726+
cs35l41_hda_pause_done(dev);
727+
mutex_unlock(&cs35l41->fw_mutex);
728+
696729
ret = pm_runtime_force_suspend(dev);
697730
if (ret) {
698731
dev_err(dev, "System Suspend Failed, unable to runtime suspend: %d\n", ret);
@@ -738,6 +771,7 @@ static int cs35l41_system_resume(struct device *dev)
738771
}
739772

740773
mutex_lock(&cs35l41->fw_mutex);
774+
741775
if (cs35l41->request_fw_load && !cs35l41->fw_request_ongoing) {
742776
cs35l41->fw_request_ongoing = true;
743777
schedule_work(&cs35l41->fw_load_work);
@@ -770,11 +804,6 @@ static int cs35l41_runtime_suspend(struct device *dev)
770804

771805
mutex_lock(&cs35l41->fw_mutex);
772806

773-
if (cs35l41->playback_started) {
774-
cs35l41_hda_pause_start(dev);
775-
cs35l41_hda_pause_done(dev);
776-
}
777-
778807
if (cs35l41->firmware_running) {
779808
ret = cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap,
780809
cs35l41->hw_cfg.bst_type);
@@ -1645,6 +1674,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41);
16451674
const struct dev_pm_ops cs35l41_hda_pm_ops = {
16461675
RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume,
16471676
cs35l41_runtime_idle)
1677+
.prepare = cs35l41_system_suspend_prep,
16481678
SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume)
16491679
};
16501680
EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, SND_HDA_SCODEC_CS35L41);

0 commit comments

Comments
 (0)