mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
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()
This commit is contained in:
commit
c7fac29967
@ -860,3 +860,35 @@ void drm_dp_aux_unregister(struct drm_dp_aux *aux)
|
||||
i2c_del_adapter(&aux->ddc);
|
||||
}
|
||||
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,
|
||||
|
||||
|
||||
/* 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_sprite_set_colorkey(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
@ -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_crtc *crtc = dig_port->base.base.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);
|
||||
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)
|
||||
}
|
||||
|
||||
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");
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
|
@ -53,8 +53,8 @@ format_is_yuv(uint32_t format)
|
||||
}
|
||||
}
|
||||
|
||||
static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
|
||||
int usecs)
|
||||
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
|
||||
int usecs)
|
||||
{
|
||||
/* paranoia */
|
||||
if (!adjusted_mode->crtc_htotal)
|
||||
@ -91,7 +91,7 @@ void intel_pipe_update_start(struct intel_crtc *crtc)
|
||||
vblank_start = DIV_ROUND_UP(vblank_start, 2);
|
||||
|
||||
/* 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;
|
||||
|
||||
local_irq_disable();
|
||||
|
@ -657,6 +657,8 @@ struct edp_vsc_psr {
|
||||
#define EDP_VSC_PSR_UPDATE_RFB (1<<1)
|
||||
#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
|
||||
drm_dp_max_link_rate(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user