drm/i915: Check PSR setup time vs. vblank length

Bspec says:
"Restriction : SRD must not be enabled when the PSR Setup time from DPCD
00071h is greater than the time for vertical blank minus one line."

Let's check for that and disallow PSR if we exceed the limit.

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>

authored by

Ville Syrjälä and committed by
Dave Airlie
dfd2e9ab 6608804b

+23 -4
+2
drivers/gpu/drm/i915/intel_drv.h
··· 1730 1731 1732 /* intel_sprite.c */ 1733 int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); 1734 int intel_sprite_set_colorkey(struct drm_device *dev, void *data, 1735 struct drm_file *file_priv);
··· 1730 1731 1732 /* intel_sprite.c */ 1733 + int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, 1734 + int usecs); 1735 int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); 1736 int intel_sprite_set_colorkey(struct drm_device *dev, void *data, 1737 struct drm_file *file_priv);
+18 -1
drivers/gpu/drm/i915/intel_psr.c
··· 327 struct drm_i915_private *dev_priv = to_i915(dev); 328 struct drm_crtc *crtc = dig_port->base.base.crtc; 329 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 330 331 lockdep_assert_held(&dev_priv->psr.lock); 332 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); ··· 368 } 369 370 if (IS_HASWELL(dev) && 371 - intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { 372 DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); 373 return false; 374 } 375
··· 327 struct drm_i915_private *dev_priv = to_i915(dev); 328 struct drm_crtc *crtc = dig_port->base.base.crtc; 329 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 330 + const struct drm_display_mode *adjusted_mode = 331 + &intel_crtc->config->base.adjusted_mode; 332 + int psr_setup_time; 333 334 lockdep_assert_held(&dev_priv->psr.lock); 335 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); ··· 365 } 366 367 if (IS_HASWELL(dev) && 368 + adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { 369 DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); 370 + return false; 371 + } 372 + 373 + psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd); 374 + if (psr_setup_time < 0) { 375 + DRM_DEBUG_KMS("PSR condition failed: Invalid PSR setup time (0x%02x)\n", 376 + intel_dp->psr_dpcd[1]); 377 + return false; 378 + } 379 + 380 + if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) > 381 + adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay - 1) { 382 + DRM_DEBUG_KMS("PSR condition failed: PSR setup time (%d us) too long\n", 383 + psr_setup_time); 384 return false; 385 } 386
+3 -3
drivers/gpu/drm/i915/intel_sprite.c
··· 53 } 54 } 55 56 - static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, 57 - int usecs) 58 { 59 /* paranoia */ 60 if (!adjusted_mode->crtc_htotal) ··· 91 vblank_start = DIV_ROUND_UP(vblank_start, 2); 92 93 /* FIXME needs to be calibrated sensibly */ 94 - min = vblank_start - usecs_to_scanlines(adjusted_mode, 100); 95 max = vblank_start - 1; 96 97 local_irq_disable();
··· 53 } 54 } 55 56 + int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, 57 + int usecs) 58 { 59 /* paranoia */ 60 if (!adjusted_mode->crtc_htotal) ··· 91 vblank_start = DIV_ROUND_UP(vblank_start, 2); 92 93 /* FIXME needs to be calibrated sensibly */ 94 + min = vblank_start - intel_usecs_to_scanlines(adjusted_mode, 100); 95 max = vblank_start - 1; 96 97 local_irq_disable();