Skip to content

Commit

Permalink
drm/i915: implement IBX hdmi transcoder select workaround
Browse files Browse the repository at this point in the history
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.

v2: Implement suggestions from Chris Wilson:
- add pipe variable to cut down on code noise
- write the reg value twice to w/a hw issues (Bspec is unclear on
  which bit actually require the write twice stuff, but better be
  paranoid about it)
- untangle the if logic

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Daniel Vetter committed Jun 6, 2012
1 parent 1523c31 commit 7a87c28
Showing 1 changed file with 31 additions and 1 deletion.
32 changes: 31 additions & 1 deletion drivers/gpu/drm/i915/intel_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,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);
Expand All @@ -591,6 +591,36 @@ 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;
int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;

if (mode != DRM_MODE_DPMS_ON) {
if (temp & SDVO_PIPE_B_SELECT) {
temp &= ~SDVO_PIPE_B_SELECT;
I915_WRITE(intel_hdmi->sdvox_reg, temp);
POSTING_READ(intel_hdmi->sdvox_reg);

/* Again we need to write this twice. */
I915_WRITE(intel_hdmi->sdvox_reg, temp);
POSTING_READ(intel_hdmi->sdvox_reg);

/* Transcoder selection bits only update
* effectively on vblank. */
if (crtc)
intel_wait_for_vblank(dev, pipe);
else
msleep(50);
}
} else {
/* Restore the transcoder select bit. */
if (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.
*/
Expand Down

0 comments on commit 7a87c28

Please sign in to comment.