aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h5
-rw-r--r--drivers/gpu/drm/i915/intel_display.c122
2 files changed, 121 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index be22aebe84f2..2dd880f2b4ae 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3811,8 +3811,9 @@
3811#define SOUTH_CHICKEN1 0xc2000 3811#define SOUTH_CHICKEN1 0xc2000
3812#define FDIA_PHASE_SYNC_SHIFT_OVR 19 3812#define FDIA_PHASE_SYNC_SHIFT_OVR 19
3813#define FDIA_PHASE_SYNC_SHIFT_EN 18 3813#define FDIA_PHASE_SYNC_SHIFT_EN 18
3814#define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2))) 3814#define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2)))
3815#define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2))) 3815#define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2)))
3816#define FDI_BC_BIFURCATION_SELECT (1 << 12)
3816#define SOUTH_CHICKEN2 0xc2004 3817#define SOUTH_CHICKEN2 0xc2004
3817#define DPLS_EDP_PPS_FIX_DIS (1<<0) 3818#define DPLS_EDP_PPS_FIX_DIS (1<<0)
3818 3819
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0b2224c592d8..4e7affd268eb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2343,6 +2343,29 @@ static void cpt_phase_pointer_enable(struct drm_device *dev, int pipe)
2343 POSTING_READ(SOUTH_CHICKEN1); 2343 POSTING_READ(SOUTH_CHICKEN1);
2344} 2344}
2345 2345
2346static void ivb_modeset_global_resources(struct drm_device *dev)
2347{
2348 struct drm_i915_private *dev_priv = dev->dev_private;
2349 struct intel_crtc *pipe_B_crtc =
2350 to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);
2351 struct intel_crtc *pipe_C_crtc =
2352 to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_C]);
2353 uint32_t temp;
2354
2355 /* When everything is off disable fdi C so that we could enable fdi B
2356 * with all lanes. XXX: This misses the case where a pipe is not using
2357 * any pch resources and so doesn't need any fdi lanes. */
2358 if (!pipe_B_crtc->base.enabled && !pipe_C_crtc->base.enabled) {
2359 WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
2360 WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
2361
2362 temp = I915_READ(SOUTH_CHICKEN1);
2363 temp &= ~FDI_BC_BIFURCATION_SELECT;
2364 DRM_DEBUG_KMS("disabling fdi C rx\n");
2365 I915_WRITE(SOUTH_CHICKEN1, temp);
2366 }
2367}
2368
2346/* The FDI link training functions for ILK/Ibexpeak. */ 2369/* The FDI link training functions for ILK/Ibexpeak. */
2347static void ironlake_fdi_link_train(struct drm_crtc *crtc) 2370static void ironlake_fdi_link_train(struct drm_crtc *crtc)
2348{ 2371{
@@ -2602,6 +2625,9 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
2602 POSTING_READ(reg); 2625 POSTING_READ(reg);
2603 udelay(150); 2626 udelay(150);
2604 2627
2628 DRM_DEBUG_KMS("FDI_RX_IIR before link train 0x%x\n",
2629 I915_READ(FDI_RX_IIR(pipe)));
2630
2605 /* enable CPU FDI TX and PCH FDI RX */ 2631 /* enable CPU FDI TX and PCH FDI RX */
2606 reg = FDI_TX_CTL(pipe); 2632 reg = FDI_TX_CTL(pipe);
2607 temp = I915_READ(reg); 2633 temp = I915_READ(reg);
@@ -2648,7 +2674,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
2648 if (temp & FDI_RX_BIT_LOCK || 2674 if (temp & FDI_RX_BIT_LOCK ||
2649 (I915_READ(reg) & FDI_RX_BIT_LOCK)) { 2675 (I915_READ(reg) & FDI_RX_BIT_LOCK)) {
2650 I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); 2676 I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
2651 DRM_DEBUG_KMS("FDI train 1 done.\n"); 2677 DRM_DEBUG_KMS("FDI train 1 done, level %i.\n", i);
2652 break; 2678 break;
2653 } 2679 }
2654 } 2680 }
@@ -2689,7 +2715,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
2689 2715
2690 if (temp & FDI_RX_SYMBOL_LOCK) { 2716 if (temp & FDI_RX_SYMBOL_LOCK) {
2691 I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); 2717 I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
2692 DRM_DEBUG_KMS("FDI train 2 done.\n"); 2718 DRM_DEBUG_KMS("FDI train 2 done, level %i.\n", i);
2693 break; 2719 break;
2694 } 2720 }
2695 } 2721 }
@@ -5013,6 +5039,88 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc,
5013 return true; 5039 return true;
5014} 5040}
5015 5041
5042static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev)
5043{
5044 struct drm_i915_private *dev_priv = dev->dev_private;
5045 uint32_t temp;
5046
5047 temp = I915_READ(SOUTH_CHICKEN1);
5048 if (temp & FDI_BC_BIFURCATION_SELECT)
5049 return;
5050
5051 WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
5052 WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
5053
5054 temp |= FDI_BC_BIFURCATION_SELECT;
5055 DRM_DEBUG_KMS("enabling fdi C rx\n");
5056 I915_WRITE(SOUTH_CHICKEN1, temp);
5057 POSTING_READ(SOUTH_CHICKEN1);
5058}
5059
5060static bool ironlake_check_fdi_lanes(struct intel_crtc *intel_crtc)
5061{
5062 struct drm_device *dev = intel_crtc->base.dev;
5063 struct drm_i915_private *dev_priv = dev->dev_private;
5064 struct intel_crtc *pipe_B_crtc =
5065 to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);
5066
5067 DRM_DEBUG_KMS("checking fdi config on pipe %i, lanes %i\n",
5068 intel_crtc->pipe, intel_crtc->fdi_lanes);
5069 if (intel_crtc->fdi_lanes > 4) {
5070 DRM_DEBUG_KMS("invalid fdi lane config on pipe %i: %i lanes\n",
5071 intel_crtc->pipe, intel_crtc->fdi_lanes);
5072 /* Clamp lanes to avoid programming the hw with bogus values. */
5073 intel_crtc->fdi_lanes = 4;
5074
5075 return false;
5076 }
5077
5078 if (dev_priv->num_pipe == 2)
5079 return true;
5080
5081 switch (intel_crtc->pipe) {
5082 case PIPE_A:
5083 return true;
5084 case PIPE_B:
5085 if (dev_priv->pipe_to_crtc_mapping[PIPE_C]->enabled &&
5086 intel_crtc->fdi_lanes > 2) {
5087 DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %i: %i lanes\n",
5088 intel_crtc->pipe, intel_crtc->fdi_lanes);
5089 /* Clamp lanes to avoid programming the hw with bogus values. */
5090 intel_crtc->fdi_lanes = 2;
5091
5092 return false;
5093 }
5094
5095 if (intel_crtc->fdi_lanes > 2)
5096 WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
5097 else
5098 cpt_enable_fdi_bc_bifurcation(dev);
5099
5100 return true;
5101 case PIPE_C:
5102 if (!pipe_B_crtc->base.enabled || pipe_B_crtc->fdi_lanes <= 2) {
5103 if (intel_crtc->fdi_lanes > 2) {
5104 DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %i: %i lanes\n",
5105 intel_crtc->pipe, intel_crtc->fdi_lanes);
5106 /* Clamp lanes to avoid programming the hw with bogus values. */
5107 intel_crtc->fdi_lanes = 2;
5108
5109 return false;
5110 }
5111 } else {
5112 DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n");
5113 return false;
5114 }
5115
5116 cpt_enable_fdi_bc_bifurcation(dev);
5117
5118 return true;
5119 default:
5120 BUG();
5121 }
5122}
5123
5016static void ironlake_set_m_n(struct drm_crtc *crtc, 5124static void ironlake_set_m_n(struct drm_crtc *crtc,
5017 struct drm_display_mode *mode, 5125 struct drm_display_mode *mode,
5018 struct drm_display_mode *adjusted_mode) 5126 struct drm_display_mode *adjusted_mode)
@@ -5211,7 +5319,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
5211 struct intel_encoder *encoder; 5319 struct intel_encoder *encoder;
5212 u32 temp; 5320 u32 temp;
5213 int ret; 5321 int ret;
5214 bool dither; 5322 bool dither, fdi_config_ok;
5215 5323
5216 for_each_encoder_on_crtc(dev, crtc, encoder) { 5324 for_each_encoder_on_crtc(dev, crtc, encoder) {
5217 switch (encoder->type) { 5325 switch (encoder->type) {
@@ -5349,8 +5457,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
5349 5457
5350 intel_set_pipe_timings(intel_crtc, mode, adjusted_mode); 5458 intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
5351 5459
5460 /* Note, this also computes intel_crtc->fdi_lanes which is used below in
5461 * ironlake_check_fdi_lanes. */
5352 ironlake_set_m_n(crtc, mode, adjusted_mode); 5462 ironlake_set_m_n(crtc, mode, adjusted_mode);
5353 5463
5464 fdi_config_ok = ironlake_check_fdi_lanes(intel_crtc);
5465
5354 if (is_cpu_edp) 5466 if (is_cpu_edp)
5355 ironlake_set_pll_edp(crtc, adjusted_mode->clock); 5467 ironlake_set_pll_edp(crtc, adjusted_mode->clock);
5356 5468
@@ -5368,7 +5480,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
5368 5480
5369 intel_update_linetime_watermarks(dev, pipe, adjusted_mode); 5481 intel_update_linetime_watermarks(dev, pipe, adjusted_mode);
5370 5482
5371 return ret; 5483 return fdi_config_ok ? ret : -EINVAL;
5372} 5484}
5373 5485
5374static int haswell_crtc_mode_set(struct drm_crtc *crtc, 5486static int haswell_crtc_mode_set(struct drm_crtc *crtc,
@@ -8331,6 +8443,8 @@ static void intel_init_display(struct drm_device *dev)
8331 /* FIXME: detect B0+ stepping and use auto training */ 8443 /* FIXME: detect B0+ stepping and use auto training */
8332 dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; 8444 dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
8333 dev_priv->display.write_eld = ironlake_write_eld; 8445 dev_priv->display.write_eld = ironlake_write_eld;
8446 dev_priv->display.modeset_global_resources =
8447 ivb_modeset_global_resources;
8334 } else if (IS_HASWELL(dev)) { 8448 } else if (IS_HASWELL(dev)) {
8335 dev_priv->display.fdi_link_train = hsw_fdi_link_train; 8449 dev_priv->display.fdi_link_train = hsw_fdi_link_train;
8336 dev_priv->display.write_eld = haswell_write_eld; 8450 dev_priv->display.write_eld = haswell_write_eld;