Skip to content

Commit c6b3cd3

Browse files
Stefan Bindingsmb49
authored andcommitted
ALSA: hda: cs35l41: Use pre and post playback hooks
BugLink: https://bugs.launchpad.net/bugs/2029199 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> Link: https://lore.kernel.org/r/20230721151816.2080453-9-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai <tiwai@suse.de> (cherry picked from commit 01ecc562936439cf6dd08b5f8c6bbed2704d9f9e linux-next) Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
1 parent a3bb17a commit c6b3cd3

1 file changed

Lines changed: 43 additions & 10 deletions

File tree

sound/pci/hda/cs35l41_hda.c

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -556,37 +556,68 @@ static void cs35l41_hda_pause_done(struct device *dev)
556556
cs35l41->playback_started = false;
557557
}
558558

559+
static void cs35l41_hda_pre_playback_hook(struct device *dev, int action)
560+
{
561+
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
562+
563+
switch (action) {
564+
case HDA_GEN_PCM_ACT_CLEANUP:
565+
mutex_lock(&cs35l41->fw_mutex);
566+
cs35l41_hda_pause_start(dev);
567+
mutex_unlock(&cs35l41->fw_mutex);
568+
break;
569+
default:
570+
break;
571+
}
572+
}
559573
static void cs35l41_hda_playback_hook(struct device *dev, int action)
560574
{
561575
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
562576

563577
switch (action) {
564578
case HDA_GEN_PCM_ACT_OPEN:
579+
/*
580+
* All amps must be resumed before we can start playing back.
581+
* This ensures, for external boost, that all amps are in AMP_SAFE mode.
582+
* Do this in HDA_GEN_PCM_ACT_OPEN, since this is run prior to any of the
583+
* other actions.
584+
*/
565585
pm_runtime_get_sync(dev);
566-
mutex_lock(&cs35l41->fw_mutex);
567-
cs35l41_hda_play_start(dev);
568-
mutex_unlock(&cs35l41->fw_mutex);
569586
break;
570587
case HDA_GEN_PCM_ACT_PREPARE:
571588
mutex_lock(&cs35l41->fw_mutex);
572-
cs35l41_hda_play_done(dev);
589+
cs35l41_hda_play_start(dev);
573590
mutex_unlock(&cs35l41->fw_mutex);
574591
break;
575592
case HDA_GEN_PCM_ACT_CLEANUP:
576593
mutex_lock(&cs35l41->fw_mutex);
577-
cs35l41_hda_pause_start(dev);
594+
cs35l41_hda_pause_done(dev);
578595
mutex_unlock(&cs35l41->fw_mutex);
579596
break;
580597
case HDA_GEN_PCM_ACT_CLOSE:
581-
mutex_lock(&cs35l41->fw_mutex);
582-
cs35l41_hda_pause_done(dev);
583-
mutex_unlock(&cs35l41->fw_mutex);
584-
598+
/*
599+
* Playback must be finished for all amps before we start runtime suspend.
600+
* This ensures no amps are playing back when we start putting them to sleep.
601+
*/
585602
pm_runtime_mark_last_busy(dev);
586603
pm_runtime_put_autosuspend(dev);
587604
break;
588605
default:
589-
dev_warn(cs35l41->dev, "Playback action not supported: %d\n", action);
606+
break;
607+
}
608+
}
609+
610+
static void cs35l41_hda_post_playback_hook(struct device *dev, int action)
611+
{
612+
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
613+
614+
switch (action) {
615+
case HDA_GEN_PCM_ACT_PREPARE:
616+
mutex_lock(&cs35l41->fw_mutex);
617+
cs35l41_hda_play_done(dev);
618+
mutex_unlock(&cs35l41->fw_mutex);
619+
break;
620+
default:
590621
break;
591622
}
592623
}
@@ -1041,6 +1072,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
10411072
ret = cs35l41_create_controls(cs35l41);
10421073

10431074
comps->playback_hook = cs35l41_hda_playback_hook;
1075+
comps->pre_playback_hook = cs35l41_hda_pre_playback_hook;
1076+
comps->post_playback_hook = cs35l41_hda_post_playback_hook;
10441077

10451078
mutex_unlock(&cs35l41->fw_mutex);
10461079

0 commit comments

Comments
 (0)