@@ -1322,6 +1322,7 @@ static inline void i915_write(struct drm_i915_private *dev_priv, u32 reg,
#define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type)
#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
+#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
@@ -1685,6 +1685,37 @@ static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock)
udelay(500);
}
+static void intel_fdi_normal_train(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int pipe = intel_crtc->pipe;
+ u32 reg, temp;
+
+ /* enable normal train */
+ reg = FDI_TX_CTL(pipe);
+ temp = I915_READ(reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE;
+ 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_NORMAL_CPT;
+ } else {
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_NONE;
+ }
+ I915_WRITE(reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE);
+
+ /* wait one idle pattern time */
+ POSTING_READ(reg);
+ udelay(1000);
+}
+
/* The FDI link training functions for ILK/Ibexpeak. */
static void ironlake_fdi_link_train(struct drm_crtc *crtc)
{
@@ -1771,27 +1802,6 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
DRM_DEBUG_KMS("FDI train done\n");
- /* enable normal train */
- reg = FDI_TX_CTL(pipe);
- temp = I915_READ(reg);
- temp &= ~FDI_LINK_TRAIN_NONE;
- temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE;
- 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_NORMAL_CPT;
- } else {
- temp &= ~FDI_LINK_TRAIN_NONE;
- temp |= FDI_LINK_TRAIN_NONE;
- }
- I915_WRITE(reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE);
-
- /* wait one idle pattern time */
- POSTING_READ(reg);
- udelay(1000);
}
static const int const snb_b_fdi_train_param [] = {
@@ -1980,7 +1990,7 @@ static void intel_clear_scanline_wait(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
u32 tmp;
- if (IS_GEN2(dev))
+ if (IS_GEN2(dev) || IS_GEN6(dev))
/* Can't break the hang on i8xx */
return;
@@ -2022,8 +2032,10 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
temp = I915_READ(PCH_LVDS);
- if ((temp & LVDS_PORT_EN) == 0)
+ if ((temp & LVDS_PORT_EN) == 0) {
I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
+ POSTING_READ(PCH_LVDS);
+ }
}
ironlake_fdi_enable(crtc);
@@ -2083,6 +2095,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
else if (pipe == 1 && (temp & TRANSB_DPLL_ENABLE) == 0)
temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
I915_WRITE(PCH_DPLL_SEL, temp);
+ POSTING_READ(PCH_DPLL_SEL);
}
/* set transcoder timing */
@@ -2094,6 +2107,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe)));
I915_WRITE(TRANS_VSYNC(pipe), I915_READ(VSYNC(pipe)));
+ intel_fdi_normal_train(crtc);
+
/* For PCH DP, enable TRANS_DP_CTL */
if (HAS_PCH_CPT(dev) &&
intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
@@ -2204,9 +2219,10 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
udelay(100);
/* Ironlake workaround, disable clock pointer after downing FDI */
- I915_WRITE(FDI_RX_CHICKEN(pipe),
- I915_READ(FDI_RX_CHICKEN(pipe) &
- ~FDI_RX_PHASE_SYNC_POINTER_ENABLE));
+ 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);
@@ -2251,12 +2267,21 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
DRM_ERROR("failed to disable transcoder\n");
}
+ /* keep bpc mask in transcoder */
+ temp = I915_READ(reg);
+ temp &= ~PIPE_BPC_MASK;
+ temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK);
+ I915_WRITE(reg, temp);
+ POSTING_READ(reg);
+ udelay(100);
+
if (HAS_PCH_CPT(dev)) {
/* disable TRANS_DP_CTL */
reg = TRANS_DP_CTL(pipe);
temp = I915_READ(reg);
temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK);
I915_WRITE(reg, temp);
+ POSTING_READ(reg);
/* disable DPLL_SEL */
temp = I915_READ(PCH_DPLL_SEL);
@@ -2265,17 +2290,20 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
else
temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
I915_WRITE(PCH_DPLL_SEL, temp);
+ POSTING_READ(PCH_DPLL_SEL);
}
/* disable PCH DPLL */
reg = PCH_DPLL(pipe);
temp = I915_READ(reg);
I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE);
+ POSTING_READ(reg);
/* Switch from PCDclk to Rawclk */
reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
I915_WRITE(reg, temp & ~FDI_PCDCLK);
+ POSTING_READ(reg);
/* Disable CPU FDI TX PLL */
reg = FDI_TX_CTL(pipe);