summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_ddi.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2018-01-22 19:41:31 +0200
committerVille Syrjälä <ville.syrjala@linux.intel.com>2018-01-24 20:09:29 +0200
commit0519c102f5285476d7868a387bdb6c58385e4074 (patch)
tree3e5adb8d546c50537447b3b76ce329200127018a /drivers/gpu/drm/i915/intel_ddi.c
parentc19e1124e7e8cb1f8fbb685fd9b7d0a42087bd62 (diff)
drm/i915: Implement display w/a #1143
Apparently SKL/KBL/CFL need some manual help to get the programmed HDMI vswing to stick. Implement the relevant workaround (display w/a #1143). Note that the relevant chicken bits live in a transcoder register even though the bits affect a specific DDI port rather than a specific transcoder. Hence we must pick the correct transcoder register instance based on the port rather than based on the cpu_transcoder. Also note that for completeness I included support for DDI A/E in the code even though we never have HDMI on those ports. v2: CFL needs the w/a as well (Rodrigo and Art) Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Art Runyan <arthur.j.runyan@intel.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180122174131.28046-1-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index f51645a08dca..2756a69b6207 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2404,6 +2404,48 @@ static void intel_enable_ddi_hdmi(struct intel_encoder *encoder,
crtc_state->hdmi_high_tmds_clock_ratio,
crtc_state->hdmi_scrambling);
+ /* Display WA #1143: skl,kbl,cfl */
+ if (IS_GEN9_BC(dev_priv)) {
+ /*
+ * For some reason these chicken bits have been
+ * stuffed into a transcoder register, event though
+ * the bits affect a specific DDI port rather than
+ * a specific transcoder.
+ */
+ static const enum transcoder port_to_transcoder[] = {
+ [PORT_A] = TRANSCODER_EDP,
+ [PORT_B] = TRANSCODER_A,
+ [PORT_C] = TRANSCODER_B,
+ [PORT_D] = TRANSCODER_C,
+ [PORT_E] = TRANSCODER_A,
+ };
+ enum transcoder transcoder = port_to_transcoder[port];
+ u32 val;
+
+ val = I915_READ(CHICKEN_TRANS(transcoder));
+
+ if (port == PORT_E)
+ val |= DDIE_TRAINING_OVERRIDE_ENABLE |
+ DDIE_TRAINING_OVERRIDE_VALUE;
+ else
+ val |= DDI_TRAINING_OVERRIDE_ENABLE |
+ DDI_TRAINING_OVERRIDE_VALUE;
+
+ I915_WRITE(CHICKEN_TRANS(transcoder), val);
+ POSTING_READ(CHICKEN_TRANS(transcoder));
+
+ udelay(1);
+
+ if (port == PORT_E)
+ val &= ~(DDIE_TRAINING_OVERRIDE_ENABLE |
+ DDIE_TRAINING_OVERRIDE_VALUE);
+ else
+ val &= ~(DDI_TRAINING_OVERRIDE_ENABLE |
+ DDI_TRAINING_OVERRIDE_VALUE);
+
+ I915_WRITE(CHICKEN_TRANS(transcoder), val);
+ }
+
/* In HDMI/DVI mode, the port width, and swing/emphasis values
* are ignored so nothing special needs to be done besides
* enabling the port.