diff options
author | Jani Nikula <jani.nikula@intel.com> | 2014-11-04 10:30:23 +0200 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-11-07 18:42:02 +0100 |
commit | 5fad84a7530f8e7664cdc6f490cb90653fed1266 (patch) | |
tree | 1b64521538499fe484c71f924b082ee5477c9199 /drivers/gpu/drm/i915/intel_audio.c | |
parent | c46f111f5171b63572fae3f79bcfe578bc96c603 (diff) | |
download | op-kernel-dev-5fad84a7530f8e7664cdc6f490cb90653fed1266.zip op-kernel-dev-5fad84a7530f8e7664cdc6f490cb90653fed1266.tar.gz |
drm/i915: rewrite hsw/bdw audio codec enable/disable sequences
There's some serious confusion regarding ELD valid bit that gets set and
cleared back and forth etc. Rewrite it all based on the documented audio
codec enable/disable sequences.
v3: replace vblank wait with a comment
v4: expand the comment on what should be done with the vblank wait
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>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_audio.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_audio.c | 115 |
1 files changed, 51 insertions, 64 deletions
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 821514c..4dcfc46 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -132,14 +132,26 @@ static void g4x_audio_codec_enable(struct drm_connector *connector, static void hsw_audio_codec_disable(struct intel_encoder *encoder) { - struct drm_device *dev = encoder->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc = encoder->base.crtc; - enum pipe pipe = to_intel_crtc(crtc)->pipe; + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); + enum pipe pipe = intel_crtc->pipe; uint32_t tmp; + DRM_DEBUG_KMS("Disable audio codec on pipe %c\n", pipe_name(pipe)); + + /* Disable timestamps */ + tmp = I915_READ(HSW_AUD_CFG(pipe)); + 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(HSW_AUD_CFG(pipe), tmp); + + /* Invalidate ELD */ tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); - tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4)); + tmp &= ~(AUDIO_ELD_VALID_A << (pipe * 4)); I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); } @@ -149,77 +161,52 @@ static void hsw_audio_codec_enable(struct drm_connector *connector, { struct drm_i915_private *dev_priv = connector->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - uint8_t *eld = connector->eld; - uint32_t eldv; + enum pipe pipe = intel_crtc->pipe; + const uint8_t *eld = connector->eld; uint32_t tmp; int len, i; - enum pipe pipe = intel_crtc->pipe; - enum port port; - int hdmiw_hdmiedid = HSW_AUD_EDID_DATA(pipe); - int aud_cntl_st = HSW_AUD_DIP_ELD_CTRL(pipe); - int aud_config = HSW_AUD_CFG(pipe); - int aud_cntrl_st2 = HSW_AUD_PIN_ELD_CP_VLD; - /* Audio output enable */ - DRM_DEBUG_DRIVER("HDMI audio: enable codec\n"); - tmp = I915_READ(aud_cntrl_st2); - tmp |= (AUDIO_OUTPUT_ENABLE_A << (pipe * 4)); - I915_WRITE(aud_cntrl_st2, tmp); - POSTING_READ(aud_cntrl_st2); - - /* Set ELD valid state */ - tmp = I915_READ(aud_cntrl_st2); - DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%08x\n", tmp); - tmp |= (AUDIO_ELD_VALID_A << (pipe * 4)); - I915_WRITE(aud_cntrl_st2, tmp); - tmp = I915_READ(aud_cntrl_st2); - DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%08x\n", tmp); - - /* Enable HDMI mode */ - tmp = I915_READ(aud_config); - DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%08x\n", tmp); - /* clear N_programing_enable and N_value_index */ - tmp &= ~(AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_N_PROG_ENABLE); - I915_WRITE(aud_config, tmp); + DRM_DEBUG_KMS("Enable audio codec on pipe %c, %u bytes ELD\n", + pipe_name(pipe), eld[2]); - DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe)); - - eldv = AUDIO_ELD_VALID_A << (pipe * 4); - - if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT)) - I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ - else - I915_WRITE(aud_config, audio_config_hdmi_pixel_clock(mode)); - - if (intel_eld_uptodate(connector, - aud_cntrl_st2, eldv, - aud_cntl_st, IBX_ELD_ADDRESS_MASK, - hdmiw_hdmiedid)) - return; + /* Enable audio presence detect, invalidate ELD */ + tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); + tmp |= AUDIO_OUTPUT_ENABLE_A << (pipe * 4); + tmp &= ~(AUDIO_ELD_VALID_A << (pipe * 4)); + I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); - tmp = I915_READ(aud_cntrl_st2); - tmp &= ~eldv; - I915_WRITE(aud_cntrl_st2, tmp); + /* + * FIXME: We're supposed to wait for vblank here, but we have vblanks + * disabled during the mode set. The proper fix would be to push the + * rest of the setup into a vblank work item, queued here, but the + * infrastructure is not there yet. + */ - tmp = I915_READ(aud_cntl_st); + /* Reset ELD write address */ + tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(pipe)); tmp &= ~IBX_ELD_ADDRESS_MASK; - I915_WRITE(aud_cntl_st, tmp); - port = (tmp >> 29) & DIP_PORT_SEL_MASK; /* DIP_Port_Select, 0x1 = PortB */ - DRM_DEBUG_DRIVER("port num:%d\n", port); + I915_WRITE(HSW_AUD_DIP_ELD_CTRL(pipe), tmp); - len = min_t(int, eld[2], 21); /* 84 bytes of hw ELD buffer */ - DRM_DEBUG_DRIVER("ELD size %d\n", len); + /* Up to 84 bytes of hw ELD buffer */ + len = min_t(int, eld[2], 21); for (i = 0; i < len; i++) - I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i)); - - tmp = I915_READ(aud_cntrl_st2); - tmp |= eldv; - I915_WRITE(aud_cntrl_st2, tmp); + I915_WRITE(HSW_AUD_EDID_DATA(pipe), *((uint32_t *)eld + i)); - /* XXX: Transitional */ + /* ELD valid */ tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); - tmp |= ((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4)); + tmp |= AUDIO_ELD_VALID_A << (pipe * 4); I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); + + /* Enable timestamps */ + tmp = I915_READ(HSW_AUD_CFG(pipe)); + 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)) + tmp |= AUD_CONFIG_N_VALUE_INDEX; + else + tmp |= audio_config_hdmi_pixel_clock(mode); + I915_WRITE(HSW_AUD_CFG(pipe), tmp); } static void ilk_audio_codec_enable(struct drm_connector *connector, |