summarylogtreecommitdiffstats
path: root/0008-ALSA-hda-cs35l41-Use-pre-and-post-playback-hooks.patch
diff options
context:
space:
mode:
Diffstat (limited to '0008-ALSA-hda-cs35l41-Use-pre-and-post-playback-hooks.patch')
-rw-r--r--0008-ALSA-hda-cs35l41-Use-pre-and-post-playback-hooks.patch122
1 files changed, 122 insertions, 0 deletions
diff --git a/0008-ALSA-hda-cs35l41-Use-pre-and-post-playback-hooks.patch b/0008-ALSA-hda-cs35l41-Use-pre-and-post-playback-hooks.patch
new file mode 100644
index 000000000000..ac5b0290b2bc
--- /dev/null
+++ b/0008-ALSA-hda-cs35l41-Use-pre-and-post-playback-hooks.patch
@@ -0,0 +1,122 @@
+From 4f3b42e2f126f96b1e512871d7073fb10d9a7283 Mon Sep 17 00:00:00 2001
+From: Stefan Binding <sbinding@opensource.cirrus.com>
+Date: Fri, 21 Jul 2023 16:18:13 +0100
+Subject: [PATCH 08/11] ALSA: hda: cs35l41: Use pre and post playback hooks
+
+Use new hooks to ensure separation between play/pause actions,
+as required by external boost.
+
+External Boost on CS35L41 requires the amp to go through a
+particular sequence of steps. One of these steps involes
+the setting of a GPIO. This GPIO is connected to one or
+more of the amps, and it may control the boost for all of
+the amps. To ensure that the GPIO is set when it is safe
+to do so, and to ensure that boost is ready for the rest of
+the sequence to be able to continue, we must ensure that
+the each part of the sequence is executed for each amp
+before moving on to the next part of the sequence.
+
+Some of the Play and Pause actions have moved from Open to
+Prepare. This is because Open is not guaranteed to be called
+again on system resume, whereas Prepare should.
+
+Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
+---
+ sound/pci/hda/cs35l41_hda.c | 53 ++++++++++++++++++++++++++++++-------
+ 1 file changed, 43 insertions(+), 10 deletions(-)
+
+diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
+index f77583b46b6b..a482d4752b3f 100644
+--- a/sound/pci/hda/cs35l41_hda.c
++++ b/sound/pci/hda/cs35l41_hda.c
+@@ -556,37 +556,68 @@ static void cs35l41_hda_pause_done(struct device *dev)
+ cs35l41->playback_started = false;
+ }
+
++static void cs35l41_hda_pre_playback_hook(struct device *dev, int action)
++{
++ struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
++
++ switch (action) {
++ case HDA_GEN_PCM_ACT_CLEANUP:
++ mutex_lock(&cs35l41->fw_mutex);
++ cs35l41_hda_pause_start(dev);
++ mutex_unlock(&cs35l41->fw_mutex);
++ break;
++ default:
++ break;
++ }
++}
+ static void cs35l41_hda_playback_hook(struct device *dev, int action)
+ {
+ struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
+
+ switch (action) {
+ case HDA_GEN_PCM_ACT_OPEN:
++ /*
++ * All amps must be resumed before we can start playing back.
++ * This ensures, for external boost, that all amps are in AMP_SAFE mode.
++ * Do this in HDA_GEN_PCM_ACT_OPEN, since this is run prior to any of the
++ * other actions.
++ */
+ pm_runtime_get_sync(dev);
+- mutex_lock(&cs35l41->fw_mutex);
+- cs35l41_hda_play_start(dev);
+- mutex_unlock(&cs35l41->fw_mutex);
+ break;
+ case HDA_GEN_PCM_ACT_PREPARE:
+ mutex_lock(&cs35l41->fw_mutex);
+- cs35l41_hda_play_done(dev);
++ cs35l41_hda_play_start(dev);
+ mutex_unlock(&cs35l41->fw_mutex);
+ break;
+ case HDA_GEN_PCM_ACT_CLEANUP:
+ mutex_lock(&cs35l41->fw_mutex);
+- cs35l41_hda_pause_start(dev);
++ cs35l41_hda_pause_done(dev);
+ mutex_unlock(&cs35l41->fw_mutex);
+ break;
+ case HDA_GEN_PCM_ACT_CLOSE:
+- mutex_lock(&cs35l41->fw_mutex);
+- cs35l41_hda_pause_done(dev);
+- 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.
++ */
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+ break;
+ default:
+- dev_warn(cs35l41->dev, "Playback action not supported: %d\n", action);
++ break;
++ }
++}
++
++static void cs35l41_hda_post_playback_hook(struct device *dev, int action)
++{
++ struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
++
++ switch (action) {
++ case HDA_GEN_PCM_ACT_PREPARE:
++ mutex_lock(&cs35l41->fw_mutex);
++ cs35l41_hda_play_done(dev);
++ mutex_unlock(&cs35l41->fw_mutex);
++ break;
++ default:
+ break;
+ }
+ }
+@@ -1037,6 +1068,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
+ ret = cs35l41_create_controls(cs35l41);
+
+ comps->playback_hook = cs35l41_hda_playback_hook;
++ comps->pre_playback_hook = cs35l41_hda_pre_playback_hook;
++ comps->post_playback_hook = cs35l41_hda_post_playback_hook;
+
+ mutex_unlock(&cs35l41->fw_mutex);
+
+--
+2.41.0
+