[Intel-gfx] [PATCH 2/3] drm/i915: implement IBX hdmi transcoder select workaround
Chris Wilson
chris at chris-wilson.co.uk
Wed May 30 12:39:11 CEST 2012
On Wed, 30 May 2012 12:31:57 +0200, Daniel Vetter <daniel.vetter at ffwll.ch> wrote:
> Bspec Vol 3, Part 3, Section 3.8.1.1, bit 30:
>
> "[DevIBX] Writing to this bit only takes effect when port is enabled.
> Due to hardware issue it is required that this bit be cleared when port
> is disabled. To clear this bit software must temporarily enable this
> port on transcoder A."
>
> Unfortunately the public Bspec misses totally out on the same language
> for HDMIB. Internal Bspec also mentions that one of the bad
> side-effects is that DPx can fail to light up on transcoder A if HDMIx
> is disabled but using transcoder B.
>
> I've found this while reviewing Bsepc. We already implement the same
> workaround for the DP ports.
>
> Also replace a magic 1 with PIPE_B I've found while looking through the
> code.
>
> Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
> ---
> drivers/gpu/drm/i915/intel_hdmi.c | 29 ++++++++++++++++++++++++++++-
> 1 files changed, 28 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 4c6f141..4ebdcf1 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -382,7 +382,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
>
> if (HAS_PCH_CPT(dev))
> sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
> - else if (intel_crtc->pipe == 1)
> + else if (intel_crtc->pipe == PIPE_B)
> sdvox |= SDVO_PIPE_B_SELECT;
>
> I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
> @@ -405,6 +405,33 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
>
> temp = I915_READ(intel_hdmi->sdvox_reg);
>
> + /* HW workaround for IBX, we need to move the port to transcoder A
> + * before disabling it. */
> + if (HAS_PCH_IBX(dev)) {
> + struct drm_crtc *crtc = encoder->crtc;
> + struct intel_crtc *intel_crtc;
> +
> + if (crtc)
> + intel_crtc = to_intel_crtc(crtc);
> + else
> + intel_crtc = NULL;
If you extracted pipe = crtc ? to_intel_crtc(crtc)->pipe : -1; then that
would make the following code less ugly.
> +
> + if (mode != DRM_MODE_DPMS_ON && (temp & SDVO_PIPE_B_SELECT)) {
Split this into a nested if:
if (mode != DPMS_MODE_DPMS_ON) {
if (temp & SDVO_PIPE_B_SELECT) {
// w/a
}
} else {
// restore
}
> + temp &= ~SDVO_PIPE_B_SELECT;
> + I915_WRITE(intel_hdmi->sdvox_reg, temp);
> + POSTING_READ(intel_hdmi->sdvox_reg);
Should we not worry about the HW w/a requiring this to be written twice?
static void intel_hdmi_write_sdvox(intel_hdmi, u32 val)
{
struct drm_i915_private *dev_priv = intel_hdmi->base.dev->dev_private;
I915_WRITE(intel_hdmi->sdvox_reg, val);
POSTING_READ(intel_hdmi->sdvo_reg);
/* HW workaround, need to write this twice for issues that may result
* in first write getting masked.
*/
if (dev_priv->info.has_pch_split) {
I915_WRITE(intel_hdmi->sdvox_reg, val);
POSTING_READ(intel_hdmi->sdvox_reg);
}
}
> +
> + if (intel_crtc)
> + intel_wait_for_vblank(dev, intel_crtc->pipe);
> + else
> + msleep(50);
> + } else if (mode == DRM_MODE_DPMS_ON){
> + /* Restore the transcoder select bit. */
> + if (intel_crtc->pipe == PIPE_B)
> + enable_bits |= SDVO_PIPE_B_SELECT;
> + }
> + }
> +
> /* HW workaround, need to toggle enable bit off and on for 12bpc, but
> * we do this anyway which shows more stable in testing.
> */
--
Chris Wilson, Intel Open Source Technology Centre
More information about the Intel-gfx
mailing list