From: Paulo Zanoni <paulo.r.zanoni at intel.com> More specifically, the LPT FDI RX only supports 8bpc and a maximum of 2 lanes, so anything above that won't work and should be rejected. Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com> --- drivers/gpu/drm/i915/intel_crt.c | 5 +++++ drivers/gpu/drm/i915/intel_display.c | 23 ++++++++++++++--------- drivers/gpu/drm/i915/intel_drv.h | 1 + 3 files changed, 20 insertions(+), 9 deletions(-) This one could go to 3.8 too. diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 5c77743..3084d01 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -198,6 +198,11 @@ static int intel_crt_mode_valid(struct drm_connector *connector, if (mode->clock > max_clock) return MODE_CLOCK_HIGH; + /* The FDI receiver on LPT only supports 8bpc and only has 2 lanes. */ + if (HAS_PCH_LPT(dev) && + (ironlake_get_lanes_required(mode->clock, 270000, 24) > 2)) + return MODE_CLOCK_HIGH; + return MODE_OK; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 78d12c4..8d86a39 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5228,6 +5228,17 @@ static bool ironlake_check_fdi_lanes(struct intel_crtc *intel_crtc) } } +int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp) +{ + /* + * Account for spread spectrum to avoid + * oversubscribing the link. Max center spread + * is 2.5%; use 5% for safety's sake. + */ + u32 bps = target_clock * bpp * 21 / 20; + return bps / (link_bw * 8) + 1; +} + static void ironlake_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -5281,15 +5292,9 @@ static void ironlake_set_m_n(struct drm_crtc *crtc, else target_clock = adjusted_mode->clock; - if (!lane) { - /* - * Account for spread spectrum to avoid - * oversubscribing the link. Max center spread - * is 2.5%; use 5% for safety's sake. - */ - u32 bps = target_clock * intel_crtc->bpp * 21 / 20; - lane = bps / (link_bw * 8) + 1; - } + if (!lane) + lane = ironlake_get_lanes_required(target_clock, link_bw, + intel_crtc->bpp); intel_crtc->fdi_lanes = lane; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 522061c..a468a07 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -556,6 +556,7 @@ intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe); extern void intel_wait_for_vblank(struct drm_device *dev, int pipe); extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe); +extern int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp); struct intel_load_detect_pipe { struct drm_framebuffer *release_fb; -- 1.7.11.7