diff options
Diffstat (limited to '0009-ALSA-hda-cs35l41-Rework-System-Suspend-to-ensure-cor.patch')
-rw-r--r-- | 0009-ALSA-hda-cs35l41-Rework-System-Suspend-to-ensure-cor.patch | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/0009-ALSA-hda-cs35l41-Rework-System-Suspend-to-ensure-cor.patch b/0009-ALSA-hda-cs35l41-Rework-System-Suspend-to-ensure-cor.patch new file mode 100644 index 000000000000..02d98e408b9f --- /dev/null +++ b/0009-ALSA-hda-cs35l41-Rework-System-Suspend-to-ensure-cor.patch @@ -0,0 +1,114 @@ +From 5091ba7ad9ea6a88db464b84b4993cc9e5033a84 Mon Sep 17 00:00:00 2001 +From: Stefan Binding <sbinding@opensource.cirrus.com> +Date: Fri, 21 Jul 2023 16:18:14 +0100 +Subject: [PATCH 09/11] ALSA: hda: cs35l41: Rework System Suspend to ensure + correct call separation + +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> +--- + sound/pci/hda/cs35l41_hda.c | 40 ++++++++++++++++++++++++++++++++----- + 1 file changed, 35 insertions(+), 5 deletions(-) + +diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c +index a482d4752b3f..70aa819cfbd6 100644 +--- a/sound/pci/hda/cs35l41_hda.c ++++ b/sound/pci/hda/cs35l41_hda.c +@@ -595,6 +595,15 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) + mutex_unlock(&cs35l41->fw_mutex); + break; + case HDA_GEN_PCM_ACT_CLOSE: ++ mutex_lock(&cs35l41->fw_mutex); ++ if (!cs35l41->firmware_running && cs35l41->request_fw_load && ++ !cs35l41->fw_request_ongoing) { ++ dev_info(dev, "Requesting Firmware Load after HDA_GEN_PCM_ACT_CLOSE\n"); ++ cs35l41->fw_request_ongoing = true; ++ schedule_work(&cs35l41->fw_load_work); ++ } ++ mutex_unlock(&cs35l41->fw_mutex); ++ + /* + * Playback must be finished for all amps before we start runtime suspend. + * 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) + return ret; + } + ++static int cs35l41_system_suspend_prep(struct device *dev) ++{ ++ struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); ++ ++ dev_dbg(cs35l41->dev, "System Suspend Prepare\n"); ++ ++ if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { ++ dev_err_once(cs35l41->dev, "System Suspend not supported\n"); ++ return 0; /* don't block the whole system suspend */ ++ } ++ ++ mutex_lock(&cs35l41->fw_mutex); ++ if (cs35l41->playback_started) ++ cs35l41_hda_pause_start(dev); ++ mutex_unlock(&cs35l41->fw_mutex); ++ ++ return 0; ++} ++ + static int cs35l41_system_suspend(struct device *dev) + { + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); +@@ -693,6 +721,11 @@ static int cs35l41_system_suspend(struct device *dev) + return 0; /* don't block the whole system suspend */ + } + ++ mutex_lock(&cs35l41->fw_mutex); ++ if (cs35l41->playback_started) ++ cs35l41_hda_pause_done(dev); ++ mutex_unlock(&cs35l41->fw_mutex); ++ + ret = pm_runtime_force_suspend(dev); + if (ret) { + 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) + } + + mutex_lock(&cs35l41->fw_mutex); ++ + if (cs35l41->request_fw_load && !cs35l41->fw_request_ongoing) { + cs35l41->fw_request_ongoing = true; + schedule_work(&cs35l41->fw_load_work); +@@ -770,11 +804,6 @@ static int cs35l41_runtime_suspend(struct device *dev) + + mutex_lock(&cs35l41->fw_mutex); + +- if (cs35l41->playback_started) { +- cs35l41_hda_pause_start(dev); +- cs35l41_hda_pause_done(dev); +- } +- + if (cs35l41->firmware_running) { + ret = cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap, + cs35l41->hw_cfg.bst_type); +@@ -1641,6 +1670,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41); + const struct dev_pm_ops cs35l41_hda_pm_ops = { + RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume, + cs35l41_runtime_idle) ++ .prepare = cs35l41_system_suspend_prep, + SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume) + }; + EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, SND_HDA_SCODEC_CS35L41); +-- +2.41.0 + |