diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-02 19:29:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-02 19:29:03 -0400 |
commit | c7fac299672ee98a1da90ea2e473180fc75d2c53 (patch) | |
tree | e0b325e271f17fe73bfe90e01118b01b3c93815c | |
parent | c8d0267efdb4ab16cd0ed6e0218e8c164006de48 (diff) | |
parent | dfd2e9ab6a7db56a5f5bb55f71485a92613c8e11 (diff) |
Merge tag 'drm-psr-fixes-for-v4.8' of git://people.freedesktop.org/~airlied/linux
Pull i915 drm fixes from Dave Airlie:
"These are the two fixes from Ville for the bug you are seeing on your
HSW laptop.
They pretty much disable PSR in some cases where the panel reports a
setup time that would cause issues, like you seem to have"
* tag 'drm-psr-fixes-for-v4.8' of git://people.freedesktop.org/~airlied/linux:
drm/i915: Check PSR setup time vs. vblank length
drm/dp: Add drm_dp_psr_setup_time()
-rw-r--r-- | drivers/gpu/drm/drm_dp_helper.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_psr.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sprite.c | 6 | ||||
-rw-r--r-- | include/drm/drm_dp_helper.h | 2 |
5 files changed, 57 insertions, 4 deletions
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 8f11b8741e42..eae5ef963cb7 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c | |||
@@ -860,3 +860,35 @@ void drm_dp_aux_unregister(struct drm_dp_aux *aux) | |||
860 | i2c_del_adapter(&aux->ddc); | 860 | i2c_del_adapter(&aux->ddc); |
861 | } | 861 | } |
862 | EXPORT_SYMBOL(drm_dp_aux_unregister); | 862 | EXPORT_SYMBOL(drm_dp_aux_unregister); |
863 | |||
864 | #define PSR_SETUP_TIME(x) [DP_PSR_SETUP_TIME_ ## x >> DP_PSR_SETUP_TIME_SHIFT] = (x) | ||
865 | |||
866 | /** | ||
867 | * drm_dp_psr_setup_time() - PSR setup in time usec | ||
868 | * @psr_cap: PSR capabilities from DPCD | ||
869 | * | ||
870 | * Returns: | ||
871 | * PSR setup time for the panel in microseconds, negative | ||
872 | * error code on failure. | ||
873 | */ | ||
874 | int drm_dp_psr_setup_time(const u8 psr_cap[EDP_PSR_RECEIVER_CAP_SIZE]) | ||
875 | { | ||
876 | static const u16 psr_setup_time_us[] = { | ||
877 | PSR_SETUP_TIME(330), | ||
878 | PSR_SETUP_TIME(275), | ||
879 | PSR_SETUP_TIME(165), | ||
880 | PSR_SETUP_TIME(110), | ||
881 | PSR_SETUP_TIME(55), | ||
882 | PSR_SETUP_TIME(0), | ||
883 | }; | ||
884 | int i; | ||
885 | |||
886 | i = (psr_cap[1] & DP_PSR_SETUP_TIME_MASK) >> DP_PSR_SETUP_TIME_SHIFT; | ||
887 | if (i >= ARRAY_SIZE(psr_setup_time_us)) | ||
888 | return -EINVAL; | ||
889 | |||
890 | return psr_setup_time_us[i]; | ||
891 | } | ||
892 | EXPORT_SYMBOL(drm_dp_psr_setup_time); | ||
893 | |||
894 | #undef PSR_SETUP_TIME | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3329fc6a95f4..cc937a19b1ba 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -1730,6 +1730,8 @@ bool intel_sdvo_init(struct drm_device *dev, | |||
1730 | 1730 | ||
1731 | 1731 | ||
1732 | /* intel_sprite.c */ | 1732 | /* intel_sprite.c */ |
1733 | int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, | ||
1734 | int usecs); | ||
1733 | int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); | 1735 | 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, | 1736 | int intel_sprite_set_colorkey(struct drm_device *dev, void *data, |
1735 | struct drm_file *file_priv); | 1737 | struct drm_file *file_priv); |
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 68bd0bb34817..2b0d1baf15b3 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c | |||
@@ -327,6 +327,9 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) | |||
327 | struct drm_i915_private *dev_priv = to_i915(dev); | 327 | struct drm_i915_private *dev_priv = to_i915(dev); |
328 | struct drm_crtc *crtc = dig_port->base.base.crtc; | 328 | struct drm_crtc *crtc = dig_port->base.base.crtc; |
329 | struct intel_crtc *intel_crtc = to_intel_crtc(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; | ||
330 | 333 | ||
331 | lockdep_assert_held(&dev_priv->psr.lock); | 334 | lockdep_assert_held(&dev_priv->psr.lock); |
332 | WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); | 335 | WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); |
@@ -365,11 +368,25 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) | |||
365 | } | 368 | } |
366 | 369 | ||
367 | if (IS_HASWELL(dev) && | 370 | if (IS_HASWELL(dev) && |
368 | intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { | 371 | adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { |
369 | DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); | 372 | DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); |
370 | return false; | 373 | return false; |
371 | } | 374 | } |
372 | 375 | ||
376 | psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd); | ||
377 | if (psr_setup_time < 0) { | ||
378 | DRM_DEBUG_KMS("PSR condition failed: Invalid PSR setup time (0x%02x)\n", | ||
379 | intel_dp->psr_dpcd[1]); | ||
380 | return false; | ||
381 | } | ||
382 | |||
383 | if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) > | ||
384 | adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay - 1) { | ||
385 | DRM_DEBUG_KMS("PSR condition failed: PSR setup time (%d us) too long\n", | ||
386 | psr_setup_time); | ||
387 | return false; | ||
388 | } | ||
389 | |||
373 | dev_priv->psr.source_ok = true; | 390 | dev_priv->psr.source_ok = true; |
374 | return true; | 391 | return true; |
375 | } | 392 | } |
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 0de935ad01c2..7c08e4f29032 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -53,8 +53,8 @@ format_is_yuv(uint32_t format) | |||
53 | } | 53 | } |
54 | } | 54 | } |
55 | 55 | ||
56 | static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, | 56 | int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, |
57 | int usecs) | 57 | int usecs) |
58 | { | 58 | { |
59 | /* paranoia */ | 59 | /* paranoia */ |
60 | if (!adjusted_mode->crtc_htotal) | 60 | if (!adjusted_mode->crtc_htotal) |
@@ -91,7 +91,7 @@ void intel_pipe_update_start(struct intel_crtc *crtc) | |||
91 | vblank_start = DIV_ROUND_UP(vblank_start, 2); | 91 | vblank_start = DIV_ROUND_UP(vblank_start, 2); |
92 | 92 | ||
93 | /* FIXME needs to be calibrated sensibly */ | 93 | /* FIXME needs to be calibrated sensibly */ |
94 | min = vblank_start - usecs_to_scanlines(adjusted_mode, 100); | 94 | min = vblank_start - intel_usecs_to_scanlines(adjusted_mode, 100); |
95 | max = vblank_start - 1; | 95 | max = vblank_start - 1; |
96 | 96 | ||
97 | local_irq_disable(); | 97 | local_irq_disable(); |
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 72dee1213268..63b8bd502444 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h | |||
@@ -657,6 +657,8 @@ struct edp_vsc_psr { | |||
657 | #define EDP_VSC_PSR_UPDATE_RFB (1<<1) | 657 | #define EDP_VSC_PSR_UPDATE_RFB (1<<1) |
658 | #define EDP_VSC_PSR_CRC_VALUES_VALID (1<<2) | 658 | #define EDP_VSC_PSR_CRC_VALUES_VALID (1<<2) |
659 | 659 | ||
660 | int drm_dp_psr_setup_time(const u8 psr_cap[EDP_PSR_RECEIVER_CAP_SIZE]); | ||
661 | |||
660 | static inline int | 662 | static inline int |
661 | drm_dp_max_link_rate(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) | 663 | drm_dp_max_link_rate(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) |
662 | { | 664 | { |