[RFC,v2,2/2] ASoC: add asoc hdmi audio trigger handler
diff mbox series

Message ID 1546827721-25586-2-git-send-email-libin.yang@intel.com
State New
Headers show
Series
  • [RFC,v2,1/2] ASoC: refine ASoC hdmi audio suspend/resume
Related show

Commit Message

Yang, Libin Jan. 7, 2019, 2:22 a.m. UTC
From: Libin Yang <libin.yang@intel.com>

The flow of ASoC hdmi audio suspend when playback is:
hdmi_codec_prepare() =>
  snd_hdac_display_power(bus, hdev->addr, true)
  snd_hdac_display_power(bus, hdev->addr, false)
suspend =>
  trigger(suspend) =>
    snd_hdac_display_power(bus, hdev->addr + HDA_CODEC_RT, false)
now, all bitmasks are cleared and display power is turned off.

Signed-off-by: Libin Yang <libin.yang@intel.com>
---
 include/sound/hda_component.h |  1 +
 sound/soc/codecs/hdac_hdmi.c  | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

Patch
diff mbox series

diff --git a/include/sound/hda_component.h b/include/sound/hda_component.h
index 2ec31b3..c7136b1 100644
--- a/include/sound/hda_component.h
+++ b/include/sound/hda_component.h
@@ -9,6 +9,7 @@ 
 
 /* virtual idx for controller */
 #define HDA_CODEC_IDX_CONTROLLER	HDA_MAX_CODECS
+#define HDA_CODEC_RT		    (HDA_CODEC_IDX_CONTROLLER + 1)
 
 #ifdef CONFIG_SND_HDA_COMPONENT
 int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index 782b323..908f83d 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -1383,11 +1383,43 @@  static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdev)
 
 }
 
+static int hdac_hdmi_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
+				 struct snd_soc_dai *dai)
+{
+	struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai);
+	struct hdac_device *hdev = hdmi->hdev;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		/*
+		 * Maybe there is a better way to avoid using
+		 * 'hdev->addr + HDA_CODEC_RT' bitmask?
+		 */
+		snd_hdac_display_power(hdev->bus, hdev->addr + HDA_CODEC_RT,
+				       true);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		snd_hdac_display_power(hdev->bus, hdev->addr + HDA_CODEC_RT,
+				       false);
+		break;
+	default:
+		/* Nothing to do */
+		break;
+	}
+
+	return 0;
+}
+
 static const struct snd_soc_dai_ops hdmi_dai_ops = {
 	.startup = hdac_hdmi_pcm_open,
 	.shutdown = hdac_hdmi_pcm_close,
 	.hw_params = hdac_hdmi_set_hw_params,
 	.set_tdm_slot = hdac_hdmi_set_tdm_slot,
+	.trigger = hdac_hdmi_pcm_trigger,
 };
 
 /*
@@ -1895,6 +1927,11 @@  static int hdmi_codec_prepare(struct device *dev)
 {
 	struct hdac_device *hdev = dev_to_hdac_dev(dev);
 
+	/*
+	 * FIXME: maybe using suspend/resume instead of
+	 * using prepare/complete can make things simpler
+	 * and no need to use 'hdev->addr + HDA_CODEC_RT'?
+	 */
 	snd_hdac_display_power(hdev->bus, hdev->addr, true);
 
 	/*