aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2013-10-29 07:04:08 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-10-29 08:52:56 -0400
commit1fbc0d789d12fec313c91912fc11733fdfbab863 (patch)
treee4fe33be028e269a32ebf865faebe3aab7009571
parent645378d85ee524e429aa4cf52806047b56cdc596 (diff)
drm/i915: Fix the PPT fdi lane bifurcate state handling on ivb
Originally I've thought that this is leftover hw state dirt from the BIOS. But after way too much helpless flailing around on my part I've noticed that the actual bug is when we change the state of an already active pipe. For example when we change the fdi lines from 2 to 3 without switching off outputs in-between we'll never see the crucial on->off transition in the ->modeset_global_resources hook the current logic relies on. Patch version 2 got this right by instead also checking whether the pipe is indeed active. But that in turn broke things when pipes have been turned off through dpms since the bifurcate enabling is done in the ->crtc_mode_set callback. To address this issues discussed with Ville in the patch review move the setting of the bifurcate bit into the ->crtc_enable hook. That way we won't wreak havoc with this state when userspace puts all other outputs into dpms off state. This also moves us forward with our overall goal to unify the modeset and dpms on paths (which we need to have to allow runtime pm in the dpms off state). Unfortunately this requires us to move the bifurcate helpers around a bit. Also update the commit message, I've misanalyzed the bug rather badly. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70507 Tested-by: Jan-Michael Brummer <jan.brummer@tabos.org> Cc: stable@vger.kernel.org Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c95
1 files changed, 48 insertions, 47 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 725f0bea1e4c..d78d33f9337d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2327,9 +2327,10 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
2327 FDI_FE_ERRC_ENABLE); 2327 FDI_FE_ERRC_ENABLE);
2328} 2328}
2329 2329
2330static bool pipe_has_enabled_pch(struct intel_crtc *intel_crtc) 2330static bool pipe_has_enabled_pch(struct intel_crtc *crtc)
2331{ 2331{
2332 return intel_crtc->base.enabled && intel_crtc->config.has_pch_encoder; 2332 return crtc->base.enabled && crtc->active &&
2333 crtc->config.has_pch_encoder;
2333} 2334}
2334 2335
2335static void ivb_modeset_global_resources(struct drm_device *dev) 2336static void ivb_modeset_global_resources(struct drm_device *dev)
@@ -2979,6 +2980,48 @@ static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
2979 I915_READ(VSYNCSHIFT(cpu_transcoder))); 2980 I915_READ(VSYNCSHIFT(cpu_transcoder)));
2980} 2981}
2981 2982
2983static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev)
2984{
2985 struct drm_i915_private *dev_priv = dev->dev_private;
2986 uint32_t temp;
2987
2988 temp = I915_READ(SOUTH_CHICKEN1);
2989 if (temp & FDI_BC_BIFURCATION_SELECT)
2990 return;
2991
2992 WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
2993 WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
2994
2995 temp |= FDI_BC_BIFURCATION_SELECT;
2996 DRM_DEBUG_KMS("enabling fdi C rx\n");
2997 I915_WRITE(SOUTH_CHICKEN1, temp);
2998 POSTING_READ(SOUTH_CHICKEN1);
2999}
3000
3001static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
3002{
3003 struct drm_device *dev = intel_crtc->base.dev;
3004 struct drm_i915_private *dev_priv = dev->dev_private;
3005
3006 switch (intel_crtc->pipe) {
3007 case PIPE_A:
3008 break;
3009 case PIPE_B:
3010 if (intel_crtc->config.fdi_lanes > 2)
3011 WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
3012 else
3013 cpt_enable_fdi_bc_bifurcation(dev);
3014
3015 break;
3016 case PIPE_C:
3017 cpt_enable_fdi_bc_bifurcation(dev);
3018
3019 break;
3020 default:
3021 BUG();
3022 }
3023}
3024
2982/* 3025/*
2983 * Enable PCH resources required for PCH ports: 3026 * Enable PCH resources required for PCH ports:
2984 * - PCH PLLs 3027 * - PCH PLLs
@@ -2997,6 +3040,9 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
2997 3040
2998 assert_pch_transcoder_disabled(dev_priv, pipe); 3041 assert_pch_transcoder_disabled(dev_priv, pipe);
2999 3042
3043 if (IS_IVYBRIDGE(dev))
3044 ivybridge_update_fdi_bc_bifurcation(intel_crtc);
3045
3000 /* Write the TU size bits before fdi link training, so that error 3046 /* Write the TU size bits before fdi link training, so that error
3001 * detection works. */ 3047 * detection works. */
3002 I915_WRITE(FDI_RX_TUSIZE1(pipe), 3048 I915_WRITE(FDI_RX_TUSIZE1(pipe),
@@ -5592,48 +5638,6 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc,
5592 return true; 5638 return true;
5593} 5639}
5594 5640
5595static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev)
5596{
5597 struct drm_i915_private *dev_priv = dev->dev_private;
5598 uint32_t temp;
5599
5600 temp = I915_READ(SOUTH_CHICKEN1);
5601 if (temp & FDI_BC_BIFURCATION_SELECT)
5602 return;
5603
5604 WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
5605 WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
5606
5607 temp |= FDI_BC_BIFURCATION_SELECT;
5608 DRM_DEBUG_KMS("enabling fdi C rx\n");
5609 I915_WRITE(SOUTH_CHICKEN1, temp);
5610 POSTING_READ(SOUTH_CHICKEN1);
5611}
5612
5613static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
5614{
5615 struct drm_device *dev = intel_crtc->base.dev;
5616 struct drm_i915_private *dev_priv = dev->dev_private;
5617
5618 switch (intel_crtc->pipe) {
5619 case PIPE_A:
5620 break;
5621 case PIPE_B:
5622 if (intel_crtc->config.fdi_lanes > 2)
5623 WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
5624 else
5625 cpt_enable_fdi_bc_bifurcation(dev);
5626
5627 break;
5628 case PIPE_C:
5629 cpt_enable_fdi_bc_bifurcation(dev);
5630
5631 break;
5632 default:
5633 BUG();
5634 }
5635}
5636
5637int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp) 5641int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp)
5638{ 5642{
5639 /* 5643 /*
@@ -5827,9 +5831,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
5827 &intel_crtc->config.fdi_m_n); 5831 &intel_crtc->config.fdi_m_n);
5828 } 5832 }
5829 5833
5830 if (IS_IVYBRIDGE(dev))
5831 ivybridge_update_fdi_bc_bifurcation(intel_crtc);
5832
5833 ironlake_set_pipeconf(crtc); 5834 ironlake_set_pipeconf(crtc);
5834 5835
5835 /* Set up the display plane register */ 5836 /* Set up the display plane register */