drm/i915/audio: add vlv/chv/gen5-7 audio codec disable sequence
authorJani Nikula <jani.nikula@intel.com>
Mon, 27 Oct 2014 14:26:55 +0000 (16:26 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 7 Nov 2014 17:42:16 +0000 (18:42 +0100)
Add support for disabling the audio codec on vlv/chv/gen5-7, similar to
hsw/bdw.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_audio.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_hdmi.c

index 8759fc50978306ef74515913069801baa81cdd70..5c2d06c71ae7f73111e00e508e24305fd5f4111b 100644 (file)
@@ -209,6 +209,56 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
        I915_WRITE(HSW_AUD_CFG(pipe), tmp);
 }
 
+static void ilk_audio_codec_disable(struct intel_encoder *encoder)
+{
+       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+       struct intel_digital_port *intel_dig_port =
+               enc_to_dig_port(&encoder->base);
+       enum port port = intel_dig_port->port;
+       enum pipe pipe = intel_crtc->pipe;
+       uint32_t tmp, eldv;
+       int aud_config;
+       int aud_cntrl_st2;
+
+       DRM_DEBUG_KMS("Disable audio codec on port %c, pipe %c\n",
+                     port_name(port), pipe_name(pipe));
+
+       if (HAS_PCH_IBX(dev_priv->dev)) {
+               aud_config = IBX_AUD_CFG(pipe);
+               aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
+       } else if (IS_VALLEYVIEW(dev_priv)) {
+               aud_config = VLV_AUD_CFG(pipe);
+               aud_cntrl_st2 = VLV_AUD_CNTL_ST2;
+       } else {
+               aud_config = CPT_AUD_CFG(pipe);
+               aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
+       }
+
+       /* Disable timestamps */
+       tmp = I915_READ(aud_config);
+       tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
+       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))
+               tmp |= AUD_CONFIG_N_VALUE_INDEX;
+       I915_WRITE(aud_config, tmp);
+
+       if (WARN_ON(!port)) {
+               eldv = IBX_ELD_VALIDB;
+               eldv |= IBX_ELD_VALIDB << 4;
+               eldv |= IBX_ELD_VALIDB << 8;
+       } else {
+               eldv = IBX_ELD_VALIDB << ((port - 1) * 4);
+       }
+
+       /* Invalidate ELD */
+       tmp = I915_READ(aud_cntrl_st2);
+       tmp &= ~eldv;
+       I915_WRITE(aud_cntrl_st2, tmp);
+}
+
 static void ilk_audio_codec_enable(struct drm_connector *connector,
                                   struct intel_encoder *encoder,
                                   struct drm_display_mode *mode)
@@ -360,10 +410,12 @@ void intel_init_audio(struct drm_device *dev)
                dev_priv->display.audio_codec_enable = g4x_audio_codec_enable;
        } else if (IS_VALLEYVIEW(dev)) {
                dev_priv->display.audio_codec_enable = ilk_audio_codec_enable;
+               dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
        } else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) {
                dev_priv->display.audio_codec_enable = hsw_audio_codec_enable;
                dev_priv->display.audio_codec_disable = hsw_audio_codec_disable;
        } else if (HAS_PCH_SPLIT(dev)) {
                dev_priv->display.audio_codec_enable = ilk_audio_codec_enable;
+               dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
        }
 }
index 5f2c206aef130bfb681879c07d5d26534197f8d8..f48a1aae2b658194179845a8aa558cc6411c61e2 100644 (file)
@@ -2454,6 +2454,10 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        struct drm_device *dev = encoder->base.dev;
+       struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+
+       if (crtc->config.has_audio)
+               intel_audio_codec_disable(encoder);
 
        /* Make sure the panel is off before trying to change the mode. But also
         * ensure that we have vdd while we switch off the panel. */
index f29026a1157da540dc2d1abd7e26db0c3e1daca9..f89f71e1f2cec8f0cfe993020606d0b58f19d884 100644 (file)
@@ -802,9 +802,13 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+       struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
        u32 temp;
        u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE;
 
+       if (crtc->config.has_audio)
+               intel_audio_codec_disable(encoder);
+
        temp = I915_READ(intel_hdmi->hdmi_reg);
 
        /* HW workaround for IBX, we need to move the port to transcoder A