diff mbox

[v8,2/2] ASoC: hdac_hdmi: Add PM support

Message ID 1456034444-10606-2-git-send-email-subhransu.s.prusty@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Subhransu S. Prusty Feb. 21, 2016, 6 a.m. UTC
From: Jeeja KP <jeeja.kp@intel.com>

The codec registers are reset during S3. So need to reconfigure
all pins and DP1.2 feature again after resume from S3. Also
reprogram the required registers if the S3 was triggered during
playback.

In suspended state ELD notify callback is not processed, So add
ELD check for all pins as well.

Also turn the codec power domain OFF which is kept ON during
controller resequencing and codec reenumeration.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
---
 sound/soc/codecs/hdac_hdmi.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

Comments

Takashi Iwai Feb. 21, 2016, 8:18 a.m. UTC | #1
On Sun, 21 Feb 2016 07:00:44 +0100,
Subhransu S. Prusty wrote:
> 
> From: Jeeja KP <jeeja.kp@intel.com>
> 
> The codec registers are reset during S3. So need to reconfigure
> all pins and DP1.2 feature again after resume from S3. Also
> reprogram the required registers if the S3 was triggered during
> playback.
> 
> In suspended state ELD notify callback is not processed, So add
> ELD check for all pins as well.
> 
> Also turn the codec power domain OFF which is kept ON during
> controller resequencing and codec reenumeration.
> 
> Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
> Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
> ---
>  sound/soc/codecs/hdac_hdmi.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 61 insertions(+)
> 
> diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
> index aa953a5..ab75b4b 100644
> --- a/sound/soc/codecs/hdac_hdmi.c
> +++ b/sound/soc/codecs/hdac_hdmi.c
> @@ -601,6 +601,26 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
>  				pin->eld.eld_buffer);
>  }
>  
> +static int hdac_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
> +		struct snd_soc_dai *dai)
> +{
> +	struct hdac_hdmi_dai_pin_map *dai_map;
> +	struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
> +	struct hdac_hdmi_priv *hdmi = hdac->private_data;
> +	int ret;
> +
> +	dai_map = &hdmi->dai_map[dai->id];
> +	if (cmd == SNDRV_PCM_TRIGGER_RESUME) {
> +		ret = hdac_hdmi_enable_pin(hdac, dai_map);
> +		if (ret < 0)
> +			return ret;
> +
> +		return hdac_hdmi_playback_prepare(substream, dai);
> +	}
> +
> +	return 0;
> +}
> +
>  static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
>  		struct snd_soc_dai *dai)
>  {
> @@ -1154,6 +1174,7 @@ static struct snd_soc_dai_ops hdmi_dai_ops = {
>  	.shutdown = hdac_hdmi_pcm_close,
>  	.hw_params = hdac_hdmi_set_hw_params,
>  	.prepare = hdac_hdmi_playback_prepare,
> +	.trigger = hdac_hdmi_trigger,
>  	.hw_free = hdac_hdmi_playback_cleanup,
>  };
>  
> @@ -1399,9 +1420,49 @@ static int hdmi_codec_remove(struct snd_soc_codec *codec)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_PM
> +static int hdmi_codec_resume(struct snd_soc_codec *codec)
> +{
> +	struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
> +	struct hdac_hdmi_priv *hdmi = edev->private_data;
> +	struct hdac_hdmi_pin *pin;
> +	struct hdac_device *hdac = &edev->hdac;
> +	struct hdac_bus *bus = hdac->bus;
> +	int err;
> +
> +	hdac_hdmi_skl_enable_all_pins(&edev->hdac);
> +	hdac_hdmi_skl_enable_dp12(&edev->hdac);
> +
> +	/* Power up afg */
> +	if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0))
> +		snd_hdac_codec_write(hdac, hdac->afg, 0,
> +			AC_VERB_SET_POWER_STATE, AC_PWRST_D0);

You don't have to wait for D0 power up unlike runtime resume?

> +	/*
> +	 * As the ELD notify callback request is not entertained while the
> +	 * device is in suspend state. Need to manually check detection of
> +	 * all pins here.
> +	 */
> +	list_for_each_entry(pin, &hdmi->pin_list, head)
> +		hdac_hdmi_present_sense(pin, 1);
> +
> +	/* Codec power is turned ON during controller resume */
> +	err = snd_hdac_display_power(bus, false);
> +	if (err < 0) {
> +		dev_err(bus->dev, "Cannot turn on display power on i915\n");

Make clear whether you're turning on or off...


Takashi
Subhransu S. Prusty Feb. 22, 2016, 2:10 a.m. UTC | #2
> >  
> > +#ifdef CONFIG_PM
> > +static int hdmi_codec_resume(struct snd_soc_codec *codec)
> > +{
> > +	struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
> > +	struct hdac_hdmi_priv *hdmi = edev->private_data;
> > +	struct hdac_hdmi_pin *pin;
> > +	struct hdac_device *hdac = &edev->hdac;
> > +	struct hdac_bus *bus = hdac->bus;
> > +	int err;
> > +
> > +	hdac_hdmi_skl_enable_all_pins(&edev->hdac);
> > +	hdac_hdmi_skl_enable_dp12(&edev->hdac);
> > +
> > +	/* Power up afg */
> > +	if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0))
> > +		snd_hdac_codec_write(hdac, hdac->afg, 0,
> > +			AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> 
> You don't have to wait for D0 power up unlike runtime resume?

Didn't see any issue yet. But yes, we should wait.

> 
> > +	/*
> > +	 * As the ELD notify callback request is not entertained while the
> > +	 * device is in suspend state. Need to manually check detection of
> > +	 * all pins here.
> > +	 */
> > +	list_for_each_entry(pin, &hdmi->pin_list, head)
> > +		hdac_hdmi_present_sense(pin, 1);
> > +
> > +	/* Codec power is turned ON during controller resume */
> > +	err = snd_hdac_display_power(bus, false);
> > +	if (err < 0) {
> > +		dev_err(bus->dev, "Cannot turn on display power on i915\n");
> 
> Make clear whether you're turning on or off...

Will fix it.

> 
> 
> Takashi
diff mbox

Patch

diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index aa953a5..ab75b4b 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -601,6 +601,26 @@  static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
 				pin->eld.eld_buffer);
 }
 
+static int hdac_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
+		struct snd_soc_dai *dai)
+{
+	struct hdac_hdmi_dai_pin_map *dai_map;
+	struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
+	struct hdac_hdmi_priv *hdmi = hdac->private_data;
+	int ret;
+
+	dai_map = &hdmi->dai_map[dai->id];
+	if (cmd == SNDRV_PCM_TRIGGER_RESUME) {
+		ret = hdac_hdmi_enable_pin(hdac, dai_map);
+		if (ret < 0)
+			return ret;
+
+		return hdac_hdmi_playback_prepare(substream, dai);
+	}
+
+	return 0;
+}
+
 static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
@@ -1154,6 +1174,7 @@  static struct snd_soc_dai_ops hdmi_dai_ops = {
 	.shutdown = hdac_hdmi_pcm_close,
 	.hw_params = hdac_hdmi_set_hw_params,
 	.prepare = hdac_hdmi_playback_prepare,
+	.trigger = hdac_hdmi_trigger,
 	.hw_free = hdac_hdmi_playback_cleanup,
 };
 
@@ -1399,9 +1420,49 @@  static int hdmi_codec_remove(struct snd_soc_codec *codec)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int hdmi_codec_resume(struct snd_soc_codec *codec)
+{
+	struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
+	struct hdac_hdmi_priv *hdmi = edev->private_data;
+	struct hdac_hdmi_pin *pin;
+	struct hdac_device *hdac = &edev->hdac;
+	struct hdac_bus *bus = hdac->bus;
+	int err;
+
+	hdac_hdmi_skl_enable_all_pins(&edev->hdac);
+	hdac_hdmi_skl_enable_dp12(&edev->hdac);
+
+	/* Power up afg */
+	if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0))
+		snd_hdac_codec_write(hdac, hdac->afg, 0,
+			AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+
+	/*
+	 * As the ELD notify callback request is not entertained while the
+	 * device is in suspend state. Need to manually check detection of
+	 * all pins here.
+	 */
+	list_for_each_entry(pin, &hdmi->pin_list, head)
+		hdac_hdmi_present_sense(pin, 1);
+
+	/* Codec power is turned ON during controller resume */
+	err = snd_hdac_display_power(bus, false);
+	if (err < 0) {
+		dev_err(bus->dev, "Cannot turn on display power on i915\n");
+		return err;
+	}
+
+	return 0;
+}
+#else
+#define hdmi_codec_resume NULL
+#endif
+
 static struct snd_soc_codec_driver hdmi_hda_codec = {
 	.probe		= hdmi_codec_probe,
 	.remove		= hdmi_codec_remove,
+	.resume		= hdmi_codec_resume,
 	.idle_bias_off	= true,
 };