Commit 011b9910 authored by Jesse Barnes's avatar Jesse Barnes Committed by Chris Wilson

drm/i915: skip FDI & PCH enabling for DP_A

eDP on the CPU doesn't need the PCH set up at all, it can in fact cause
problems.  So avoid FDI training and PCH PLL enabling in that case.
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Tested-by: default avatarAndy Whitcroft <apw@canonical.com>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent bdb8b975
...@@ -2045,6 +2045,31 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) ...@@ -2045,6 +2045,31 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
atomic_read(&obj->pending_flip) == 0); atomic_read(&obj->pending_flip) == 0);
} }
static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *encoder;
/*
* If there's a non-PCH eDP on this crtc, it must be DP_A, and that
* must be driven by its own crtc; no sharing is possible.
*/
list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
if (encoder->base.crtc != crtc)
continue;
switch (encoder->type) {
case INTEL_OUTPUT_EDP:
if (!intel_encoder_is_pch_edp(&encoder->base))
return false;
continue;
}
}
return true;
}
static void ironlake_crtc_enable(struct drm_crtc *crtc) static void ironlake_crtc_enable(struct drm_crtc *crtc)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
...@@ -2053,6 +2078,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -2053,6 +2078,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane; int plane = intel_crtc->plane;
u32 reg, temp; u32 reg, temp;
bool is_pch_port = false;
if (intel_crtc->active) if (intel_crtc->active)
return; return;
...@@ -2066,7 +2092,56 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -2066,7 +2092,56 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN); I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
} }
is_pch_port = intel_crtc_driving_pch(crtc);
if (is_pch_port)
ironlake_fdi_enable(crtc); ironlake_fdi_enable(crtc);
else {
/* disable CPU FDI tx and PCH FDI rx */
reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
I915_WRITE(reg, temp & ~FDI_TX_ENABLE);
POSTING_READ(reg);
reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~(0x7 << 16);
temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
POSTING_READ(reg);
udelay(100);
/* Ironlake workaround, disable clock pointer after downing FDI */
if (HAS_PCH_IBX(dev))
I915_WRITE(FDI_RX_CHICKEN(pipe),
I915_READ(FDI_RX_CHICKEN(pipe) &
~FDI_RX_PHASE_SYNC_POINTER_ENABLE));
/* still set train pattern 1 */
reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_1;
I915_WRITE(reg, temp);
reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
if (HAS_PCH_CPT(dev)) {
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
} else {
temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_1;
}
/* BPC in FDI rx is consistent with that in PIPECONF */
temp &= ~(0x07 << 16);
temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
I915_WRITE(reg, temp);
POSTING_READ(reg);
udelay(100);
}
/* Enable panel fitting for LVDS */ /* Enable panel fitting for LVDS */
if (dev_priv->pch_pf_size && if (dev_priv->pch_pf_size &&
...@@ -2100,6 +2175,10 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -2100,6 +2175,10 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
intel_flush_display_plane(dev, plane); intel_flush_display_plane(dev, plane);
} }
/* Skip the PCH stuff if possible */
if (!is_pch_port)
goto done;
/* For PCH output, training FDI link */ /* For PCH output, training FDI link */
if (IS_GEN6(dev)) if (IS_GEN6(dev))
gen6_fdi_link_train(crtc); gen6_fdi_link_train(crtc);
...@@ -2184,7 +2263,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -2184,7 +2263,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
I915_WRITE(reg, temp | TRANS_ENABLE); I915_WRITE(reg, temp | TRANS_ENABLE);
if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100)) if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
DRM_ERROR("failed to enable transcoder %d\n", pipe); DRM_ERROR("failed to enable transcoder %d\n", pipe);
done:
intel_crtc_load_lut(crtc); intel_crtc_load_lut(crtc);
intel_update_fbc(dev); intel_update_fbc(dev);
intel_crtc_update_cursor(crtc, true); intel_crtc_update_cursor(crtc, true);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment