[2/4] i915: add support for GPU side of MST audio
diff mbox

Message ID 1434513719-3580-3-git-send-email-airlied@gmail.com
State New
Headers show

Commit Message

Dave Airlie June 17, 2015, 4:01 a.m. UTC
From: Dave Airlie <airlied@redhat.com>

This just adds enables for the codecs and debugfs
support for mst connectors to print the audio info.

This relies on patches to the audio code to do anything
more useful.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 13 +++++++++++++
 drivers/gpu/drm/i915/intel_audio.c  |  7 ++++---
 drivers/gpu/drm/i915/intel_dp_mst.c | 25 +++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 3 deletions(-)

Comments

Chris Wilson June 17, 2015, 8:07 a.m. UTC | #1
On Wed, Jun 17, 2015 at 02:01:57PM +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied@redhat.com>
> 
> This just adds enables for the codecs and debugfs
> support for mst connectors to print the audio info.
> 
> This relies on patches to the audio code to do anything
> more useful.
> 
> Signed-off-by: Dave Airlie <airlied@redhat.com>
> ---
> @@ -231,6 +231,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
>  	/* Reset ELD write address */
>  	tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(pipe));
>  	tmp &= ~IBX_ELD_ADDRESS_MASK;
> +	tmp |= ((pipe + 1) << 29);
>  	I915_WRITE(HSW_AUD_DIP_ELD_CTRL(pipe), tmp);

This is not MST specific. Is this a bug fix we want ASAP?
-Chris
Daniel Vetter June 17, 2015, 11:27 a.m. UTC | #2
On Wed, Jun 17, 2015 at 02:01:57PM +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied@redhat.com>
> 
> This just adds enables for the codecs and debugfs
> support for mst connectors to print the audio info.
> 
> This relies on patches to the audio code to do anything
> more useful.
> 
> Signed-off-by: Dave Airlie <airlied@redhat.com>

Might be time to refactor all the ddi code a bit since this duplicates a
lot. Otoh the code in intel_ddi.c is full of presonality confusion
if-ladders which ain't pretty either.

Anyway this duplicates what we do for sst audio, and I guess that makes
sense. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> since I lack clue
for a real r-b.

Feel free to merge through whatever tree you want if the audio folks keep
on being offline. But perhaps first resend again with alsa-devel on cc.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 13 +++++++++++++
>  drivers/gpu/drm/i915/intel_audio.c  |  7 ++++---
>  drivers/gpu/drm/i915/intel_dp_mst.c | 25 +++++++++++++++++++++++++
>  3 files changed, 42 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index dc55c51..a109a21 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2577,6 +2577,17 @@ static void intel_dp_info(struct seq_file *m,
>  		intel_panel_info(m, &intel_connector->panel);
>  }
>  
> +static void intel_dp_mst_info(struct seq_file *m,
> +			  struct intel_connector *intel_connector)
> +{
> +	struct intel_encoder *intel_encoder = intel_connector->encoder;
> +	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&intel_encoder->base);
> +	struct intel_digital_port *intel_dig_port = intel_mst->primary;
> +	struct intel_dp *intel_dp = &intel_dig_port->dp;
> +
> +	seq_printf(m, "\taudio support: %s\n", drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, intel_connector->port) ? "yes" : "no");
> +}
> +
>  static void intel_hdmi_info(struct seq_file *m,
>  			    struct intel_connector *intel_connector)
>  {
> @@ -2621,6 +2632,8 @@ static void intel_connector_info(struct seq_file *m,
>  			intel_hdmi_info(m, intel_connector);
>  		else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
>  			intel_lvds_info(m, intel_connector);
> +		else if (intel_encoder->type == INTEL_OUTPUT_DP_MST)
> +			intel_dp_mst_info(m, intel_connector);
>  	}
>  
>  	seq_printf(m, "\tmodes:\n");
> diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
> index 2396cc7..77d2a01 100644
> --- a/drivers/gpu/drm/i915/intel_audio.c
> +++ b/drivers/gpu/drm/i915/intel_audio.c
> @@ -190,7 +190,7 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder)
>  	tmp |= AUD_CONFIG_N_PROG_ENABLE;
>  	tmp &= ~AUD_CONFIG_UPPER_N_MASK;
>  	tmp &= ~AUD_CONFIG_LOWER_N_MASK;
> -	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
> +	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST))
>  		tmp |= AUD_CONFIG_N_VALUE_INDEX;
>  	I915_WRITE(HSW_AUD_CFG(pipe), tmp);
>  
> @@ -231,6 +231,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
>  	/* Reset ELD write address */
>  	tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(pipe));
>  	tmp &= ~IBX_ELD_ADDRESS_MASK;
> +	tmp |= ((pipe + 1) << 29);
>  	I915_WRITE(HSW_AUD_DIP_ELD_CTRL(pipe), tmp);
>  
>  	/* Up to 84 bytes of hw ELD buffer */
> @@ -248,7 +249,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
>  	tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
>  	tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
>  	tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
> -	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
> +	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST))
>  		tmp |= AUD_CONFIG_N_VALUE_INDEX;
>  	else
>  		tmp |= audio_config_hdmi_pixel_clock(mode);
> @@ -417,7 +418,7 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
>  
>  	/* ELD Conn_Type */
>  	connector->eld[5] &= ~(3 << 2);
> -	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
> +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(crtc, INTEL_OUTPUT_DP_MST))
>  		connector->eld[5] |= (1 << 2);
>  
>  	connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> index 5cb4748..8a39e99 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> @@ -85,6 +85,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
>  		return false;
>  	}
>  
> +	if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, found->port))
> +		pipe_config->has_audio = true;
>  	mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->clock, bpp);
>  
>  	pipe_config->pbn = mst_pbn;
> @@ -105,6 +107,11 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
>  	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
>  	struct intel_digital_port *intel_dig_port = intel_mst->primary;
>  	struct intel_dp *intel_dp = &intel_dig_port->dp;
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct drm_crtc *crtc = encoder->base.crtc;
> +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +
>  	int ret;
>  
>  	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> @@ -115,6 +122,10 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
>  	if (ret) {
>  		DRM_ERROR("failed to update payload %d\n", ret);
>  	}
> +	if (intel_crtc->config->has_audio) {
> +		intel_audio_codec_disable(encoder);
> +		intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
> +	}
>  }
>  
>  static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
> @@ -209,6 +220,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder)
>  	struct intel_dp *intel_dp = &intel_dig_port->dp;
>  	struct drm_device *dev = intel_dig_port->base.base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
>  	enum port port = intel_dig_port->port;
>  	int ret;
>  
> @@ -221,6 +233,13 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder)
>  	ret = drm_dp_check_act_status(&intel_dp->mst_mgr);
>  
>  	ret = drm_dp_update_payload_part2(&intel_dp->mst_mgr);
> +
> +	if (crtc->config->has_audio) {
> +		DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
> +				 pipe_name(crtc->pipe));
> +		intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
> +		intel_audio_codec_enable(encoder);
> +	}
>  }
>  
>  static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder,
> @@ -246,6 +265,12 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder,
>  
>  	pipe_config->has_dp_encoder = true;
>  
> +       if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
> +                temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
> +                if (temp & AUDIO_OUTPUT_ENABLE(crtc->pipe))
> +                        pipe_config->has_audio = true;
> +        }
> +
>  	temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
>  	if (temp & TRANS_DDI_PHSYNC)
>  		flags |= DRM_MODE_FLAG_PHSYNC;
> -- 
> 2.4.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Jani Nikula June 17, 2015, 11:54 a.m. UTC | #3
On Wed, 17 Jun 2015, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> On Wed, Jun 17, 2015 at 02:01:57PM +1000, Dave Airlie wrote:
>> From: Dave Airlie <airlied@redhat.com>
>> 
>> This just adds enables for the codecs and debugfs
>> support for mst connectors to print the audio info.
>> 
>> This relies on patches to the audio code to do anything
>> more useful.
>> 
>> Signed-off-by: Dave Airlie <airlied@redhat.com>
>> ---
>> @@ -231,6 +231,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
>>  	/* Reset ELD write address */
>>  	tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(pipe));
>>  	tmp &= ~IBX_ELD_ADDRESS_MASK;
>> +	tmp |= ((pipe + 1) << 29);
>>  	I915_WRITE(HSW_AUD_DIP_ELD_CTRL(pipe), tmp);
>
> This is not MST specific. Is this a bug fix we want ASAP?


"""
This read-only bit reflects which port is used to transmit the DIP
data. This can only change when DIP is disabled. If one or more
audio-related DIP packets is enabled and audio is enabled on a digital
port, these bits will reflect the digital port to which audio is
directed.

For DP MST, this is the device select/pipe select.
"""

We shouldn't mess with the field if it's regular DP. Also "pipe + 1" is
too magic; unfortunately I don't know what it should be. :(

BR,
Jani.







> -Chris
>
> -- 
> Chris Wilson, Intel Open Source Technology Centre
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Jani Nikula June 17, 2015, 11:56 a.m. UTC | #4
On Wed, 17 Jun 2015, Jani Nikula <jani.nikula@linux.intel.com> wrote:
> On Wed, 17 Jun 2015, Chris Wilson <chris@chris-wilson.co.uk> wrote:
>> On Wed, Jun 17, 2015 at 02:01:57PM +1000, Dave Airlie wrote:
>>> From: Dave Airlie <airlied@redhat.com>
>>> 
>>> This just adds enables for the codecs and debugfs
>>> support for mst connectors to print the audio info.
>>> 
>>> This relies on patches to the audio code to do anything
>>> more useful.
>>> 
>>> Signed-off-by: Dave Airlie <airlied@redhat.com>
>>> ---
>>> @@ -231,6 +231,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
>>>  	/* Reset ELD write address */
>>>  	tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(pipe));
>>>  	tmp &= ~IBX_ELD_ADDRESS_MASK;
>>> +	tmp |= ((pipe + 1) << 29);
>>>  	I915_WRITE(HSW_AUD_DIP_ELD_CTRL(pipe), tmp);
>>
>> This is not MST specific. Is this a bug fix we want ASAP?
>
>
> """
> This read-only bit reflects which port is used to transmit the DIP
> data. This can only change when DIP is disabled. If one or more
> audio-related DIP packets is enabled and audio is enabled on a digital
> port, these bits will reflect the digital port to which audio is
> directed.
>
> For DP MST, this is the device select/pipe select.
> """
>
> We shouldn't mess with the field if it's regular DP. Also "pipe + 1" is
> too magic; unfortunately I don't know what it should be. :(

Also, should mask out anything that was there before!

BR,
Jani.

>
> BR,
> Jani.
>
>
>
>
>
>
>
>> -Chris
>>
>> -- 
>> Chris Wilson, Intel Open Source Technology Centre
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> -- 
> Jani Nikula, Intel Open Source Technology Center
Lin, Mengdong June 19, 2015, 6:27 a.m. UTC | #5
> -----Original Message-----

> From: Intel-gfx [mailto:intel-gfx-bounces@lists.freedesktop.org] On Behalf Of

> Jani Nikula

 
> On Wed, 17 Jun 2015, Chris Wilson <chris@chris-wilson.co.uk> wrote:

> > On Wed, Jun 17, 2015 at 02:01:57PM +1000, Dave Airlie wrote:

> >> From: Dave Airlie <airlied@redhat.com>

> >>

> >> This just adds enables for the codecs and debugfs support for mst

> >> connectors to print the audio info.

> >>

> >> This relies on patches to the audio code to do anything more useful.

> >>

> >> Signed-off-by: Dave Airlie <airlied@redhat.com>

> >> ---

> >> @@ -231,6 +231,7 @@ static void hsw_audio_codec_enable(struct

> drm_connector *connector,

> >>  	/* Reset ELD write address */

> >>  	tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(pipe));

> >>  	tmp &= ~IBX_ELD_ADDRESS_MASK;

> >> +	tmp |= ((pipe + 1) << 29);


I think we should not add this line.
DIP Port Select [Bit 30:29 ]of register AUD_DIP_ELD_CTRL_ST is ReadOnly.

For DP MST, I think the device select happens in both i915 driver and
HD-Audio driver:
- For i915 driver, it should select which transcoder/pipe is connected to a
device on a port. MST allows 3 devices on a port. 
Could someone guide me to the code?
The Bit 30:29 just reflect the selection, although I think this is not enough
because it only tell the port number, but now we hope know the device
entry on a port.

- For audio driver, it should select which convertor is connected to a device
of a codec pin (pin is a mapping for a DDI port). We need to add the support
in HD-A driver. The default device entry is 0 for a pin. Current HD-A driver
does not handle other 2 device entries on a pin.

Thanks
Mengdong

> >>  	I915_WRITE(HSW_AUD_DIP_ELD_CTRL(pipe), tmp);

> >

> > This is not MST specific. Is this a bug fix we want ASAP?

> 

> 

> """

> This read-only bit reflects which port is used to transmit the DIP data. This can

> only change when DIP is disabled. If one or more audio-related DIP packets is

> enabled and audio is enabled on a digital port, these bits will reflect the digital

> port to which audio is directed.

> 

> For DP MST, this is the device select/pipe select.

> """

> 

> We shouldn't mess with the field if it's regular DP. Also "pipe + 1" is too magic;

> unfortunately I don't know what it should be. :(

> 

> BR,

> Jani.

> 

> 

> 

> 

> 

> 

> 

> > -Chris

> >

> > --

> > Chris Wilson, Intel Open Source Technology Centre

> > _______________________________________________

> > Intel-gfx mailing list

> > Intel-gfx@lists.freedesktop.org

> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx

> 

> --

> Jani Nikula, Intel Open Source Technology Center

> _______________________________________________

> Intel-gfx mailing list

> Intel-gfx@lists.freedesktop.org

> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Patch
diff mbox

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index dc55c51..a109a21 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2577,6 +2577,17 @@  static void intel_dp_info(struct seq_file *m,
 		intel_panel_info(m, &intel_connector->panel);
 }
 
+static void intel_dp_mst_info(struct seq_file *m,
+			  struct intel_connector *intel_connector)
+{
+	struct intel_encoder *intel_encoder = intel_connector->encoder;
+	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&intel_encoder->base);
+	struct intel_digital_port *intel_dig_port = intel_mst->primary;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+
+	seq_printf(m, "\taudio support: %s\n", drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, intel_connector->port) ? "yes" : "no");
+}
+
 static void intel_hdmi_info(struct seq_file *m,
 			    struct intel_connector *intel_connector)
 {
@@ -2621,6 +2632,8 @@  static void intel_connector_info(struct seq_file *m,
 			intel_hdmi_info(m, intel_connector);
 		else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
 			intel_lvds_info(m, intel_connector);
+		else if (intel_encoder->type == INTEL_OUTPUT_DP_MST)
+			intel_dp_mst_info(m, intel_connector);
 	}
 
 	seq_printf(m, "\tmodes:\n");
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 2396cc7..77d2a01 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -190,7 +190,7 @@  static void hsw_audio_codec_disable(struct intel_encoder *encoder)
 	tmp |= AUD_CONFIG_N_PROG_ENABLE;
 	tmp &= ~AUD_CONFIG_UPPER_N_MASK;
 	tmp &= ~AUD_CONFIG_LOWER_N_MASK;
-	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
+	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST))
 		tmp |= AUD_CONFIG_N_VALUE_INDEX;
 	I915_WRITE(HSW_AUD_CFG(pipe), tmp);
 
@@ -231,6 +231,7 @@  static void hsw_audio_codec_enable(struct drm_connector *connector,
 	/* Reset ELD write address */
 	tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(pipe));
 	tmp &= ~IBX_ELD_ADDRESS_MASK;
+	tmp |= ((pipe + 1) << 29);
 	I915_WRITE(HSW_AUD_DIP_ELD_CTRL(pipe), tmp);
 
 	/* Up to 84 bytes of hw ELD buffer */
@@ -248,7 +249,7 @@  static void hsw_audio_codec_enable(struct drm_connector *connector,
 	tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
 	tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
 	tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
-	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
+	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST))
 		tmp |= AUD_CONFIG_N_VALUE_INDEX;
 	else
 		tmp |= audio_config_hdmi_pixel_clock(mode);
@@ -417,7 +418,7 @@  void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
 
 	/* ELD Conn_Type */
 	connector->eld[5] &= ~(3 << 2);
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(crtc, INTEL_OUTPUT_DP_MST))
 		connector->eld[5] |= (1 << 2);
 
 	connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 5cb4748..8a39e99 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -85,6 +85,8 @@  static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
 		return false;
 	}
 
+	if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, found->port))
+		pipe_config->has_audio = true;
 	mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->clock, bpp);
 
 	pipe_config->pbn = mst_pbn;
@@ -105,6 +107,11 @@  static void intel_mst_disable_dp(struct intel_encoder *encoder)
 	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
 	struct intel_digital_port *intel_dig_port = intel_mst->primary;
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = encoder->base.crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
 	int ret;
 
 	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
@@ -115,6 +122,10 @@  static void intel_mst_disable_dp(struct intel_encoder *encoder)
 	if (ret) {
 		DRM_ERROR("failed to update payload %d\n", ret);
 	}
+	if (intel_crtc->config->has_audio) {
+		intel_audio_codec_disable(encoder);
+		intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
+	}
 }
 
 static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
@@ -209,6 +220,7 @@  static void intel_mst_enable_dp(struct intel_encoder *encoder)
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
 	enum port port = intel_dig_port->port;
 	int ret;
 
@@ -221,6 +233,13 @@  static void intel_mst_enable_dp(struct intel_encoder *encoder)
 	ret = drm_dp_check_act_status(&intel_dp->mst_mgr);
 
 	ret = drm_dp_update_payload_part2(&intel_dp->mst_mgr);
+
+	if (crtc->config->has_audio) {
+		DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
+				 pipe_name(crtc->pipe));
+		intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
+		intel_audio_codec_enable(encoder);
+	}
 }
 
 static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder,
@@ -246,6 +265,12 @@  static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder,
 
 	pipe_config->has_dp_encoder = true;
 
+       if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
+                temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
+                if (temp & AUDIO_OUTPUT_ENABLE(crtc->pipe))
+                        pipe_config->has_audio = true;
+        }
+
 	temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
 	if (temp & TRANS_DDI_PHSYNC)
 		flags |= DRM_MODE_FLAG_PHSYNC;