Skip to content

Commit

Permalink
Merge tag 'drm-psr-fixes-for-v4.8' of git://people.freedesktop.org/~a…
Browse files Browse the repository at this point in the history
…irlied/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()
  • Loading branch information
torvalds committed Aug 2, 2016
2 parents c8d0267 + dfd2e9a commit c7fac29
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 4 deletions.
32 changes: 32 additions & 0 deletions drivers/gpu/drm/drm_dp_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
19 changes: 18 additions & 1 deletion drivers/gpu/drm/i915/intel_psr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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;
}
Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/i915/intel_sprite.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 2 additions & 0 deletions include/drm/drm_dp_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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])
{
Expand Down

0 comments on commit c7fac29

Please sign in to comment.