Commit c7fac299 authored by Linus Torvalds's avatar Linus Torvalds

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()
parents c8d0267e dfd2e9ab
...@@ -860,3 +860,35 @@ void drm_dp_aux_unregister(struct drm_dp_aux *aux) ...@@ -860,3 +860,35 @@ void drm_dp_aux_unregister(struct drm_dp_aux *aux)
i2c_del_adapter(&aux->ddc); i2c_del_adapter(&aux->ddc);
} }
EXPORT_SYMBOL(drm_dp_aux_unregister); EXPORT_SYMBOL(drm_dp_aux_unregister);
#define PSR_SETUP_TIME(x) [DP_PSR_SETUP_TIME_ ## x >> DP_PSR_SETUP_TIME_SHIFT] = (x)
/**
* drm_dp_psr_setup_time() - PSR setup in time usec
* @psr_cap: PSR capabilities from DPCD
*
* Returns:
* PSR setup time for the panel in microseconds, negative
* error code on failure.
*/
int drm_dp_psr_setup_time(const u8 psr_cap[EDP_PSR_RECEIVER_CAP_SIZE])
{
static const u16 psr_setup_time_us[] = {
PSR_SETUP_TIME(330),
PSR_SETUP_TIME(275),
PSR_SETUP_TIME(165),
PSR_SETUP_TIME(110),
PSR_SETUP_TIME(55),
PSR_SETUP_TIME(0),
};
int i;
i = (psr_cap[1] & DP_PSR_SETUP_TIME_MASK) >> DP_PSR_SETUP_TIME_SHIFT;
if (i >= ARRAY_SIZE(psr_setup_time_us))
return -EINVAL;
return psr_setup_time_us[i];
}
EXPORT_SYMBOL(drm_dp_psr_setup_time);
#undef PSR_SETUP_TIME
...@@ -1730,6 +1730,8 @@ bool intel_sdvo_init(struct drm_device *dev, ...@@ -1730,6 +1730,8 @@ bool intel_sdvo_init(struct drm_device *dev,
/* intel_sprite.c */ /* intel_sprite.c */
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
int usecs);
int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
int intel_sprite_set_colorkey(struct drm_device *dev, void *data, int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
......
...@@ -327,6 +327,9 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) ...@@ -327,6 +327,9 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_crtc *crtc = dig_port->base.base.crtc; struct drm_crtc *crtc = dig_port->base.base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
const struct drm_display_mode *adjusted_mode =
&intel_crtc->config->base.adjusted_mode;
int psr_setup_time;
lockdep_assert_held(&dev_priv->psr.lock); lockdep_assert_held(&dev_priv->psr.lock);
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); 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,11 +368,25 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
} }
if (IS_HASWELL(dev) && if (IS_HASWELL(dev) &&
intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
return false; return false;
} }
psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
if (psr_setup_time < 0) {
DRM_DEBUG_KMS("PSR condition failed: Invalid PSR setup time (0x%02x)\n",
intel_dp->psr_dpcd[1]);
return false;
}
if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay - 1) {
DRM_DEBUG_KMS("PSR condition failed: PSR setup time (%d us) too long\n",
psr_setup_time);
return false;
}
dev_priv->psr.source_ok = true; dev_priv->psr.source_ok = true;
return true; return true;
} }
......
...@@ -53,7 +53,7 @@ format_is_yuv(uint32_t format) ...@@ -53,7 +53,7 @@ format_is_yuv(uint32_t format)
} }
} }
static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
int usecs) int usecs)
{ {
/* paranoia */ /* paranoia */
...@@ -91,7 +91,7 @@ void intel_pipe_update_start(struct intel_crtc *crtc) ...@@ -91,7 +91,7 @@ void intel_pipe_update_start(struct intel_crtc *crtc)
vblank_start = DIV_ROUND_UP(vblank_start, 2); vblank_start = DIV_ROUND_UP(vblank_start, 2);
/* FIXME needs to be calibrated sensibly */ /* FIXME needs to be calibrated sensibly */
min = vblank_start - usecs_to_scanlines(adjusted_mode, 100); min = vblank_start - intel_usecs_to_scanlines(adjusted_mode, 100);
max = vblank_start - 1; max = vblank_start - 1;
local_irq_disable(); local_irq_disable();
......
...@@ -657,6 +657,8 @@ struct edp_vsc_psr { ...@@ -657,6 +657,8 @@ struct edp_vsc_psr {
#define EDP_VSC_PSR_UPDATE_RFB (1<<1) #define EDP_VSC_PSR_UPDATE_RFB (1<<1)
#define EDP_VSC_PSR_CRC_VALUES_VALID (1<<2) #define EDP_VSC_PSR_CRC_VALUES_VALID (1<<2)
int drm_dp_psr_setup_time(const u8 psr_cap[EDP_PSR_RECEIVER_CAP_SIZE]);
static inline int static inline int
drm_dp_max_link_rate(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) drm_dp_max_link_rate(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment