Commit a5509abd authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Fix legacy cursor vs. watermarks for ILK-BDW

In order to make cursor updates actually safe wrt. watermark programming
we have to clear the legacy_cursor_update flag in the atomic state. That
will cause the regular atomic update path to do the necessary vblank
wait after the plane update if needed, otherwise the vblank wait would
be skipped and we'd feed the optimal watermarks to the hardware before
the plane update has actually happened.

To make the slow vs. fast path determination in
intel_legacy_cursor_update() a little simpler we can ignore the actual
visibility of the plane (which can only get computed once we've already
chosen out path) and instead we simply check whether the fb is being
set or cleared by the user. This means a fully clipped but logically
visible cursor will be considered visible as far as watermark
programming is concerned. We can do that for the cursor since it's a
fixed size plane and the clipped size doesn't play a role in the
watermark computation.

This should fix underruns that can occur when the cursor gets
enable/disabled or the size gets changed. Hopefully it's good enough
that only pure cursor movement and flips go through unthrottled.

Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Uwe Kleine-König <uwe@kleine-koenig.org>
Reported-by: default avatarUwe Kleine-König <uwe@kleine-koenig.org>
Fixes: f79f2692 ("drm/i915: Add a cursor hack to allow converting legacy page flip to atomic, v3.")
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170217150159.11683-1-ville.syrjala@linux.intel.comReviewed-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Tested-by: default avatarRafael Ristovski <rafael.ristovski@gmail.com>
parent 9ce53745
...@@ -12955,6 +12955,17 @@ static int intel_atomic_commit(struct drm_device *dev, ...@@ -12955,6 +12955,17 @@ static int intel_atomic_commit(struct drm_device *dev,
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
int ret = 0; int ret = 0;
/*
* The intel_legacy_cursor_update() fast path takes care
* of avoiding the vblank waits for simple cursor
* movement and flips. For cursor on/off and size changes,
* we want to perform the vblank waits so that watermark
* updates happen during the correct frames. Gen9+ have
* double buffered watermarks and so shouldn't need this.
*/
if (INTEL_GEN(dev_priv) < 9)
state->legacy_cursor_update = false;
ret = drm_atomic_helper_setup_commit(state, nonblock); ret = drm_atomic_helper_setup_commit(state, nonblock);
if (ret) if (ret)
return ret; return ret;
...@@ -13389,8 +13400,7 @@ intel_legacy_cursor_update(struct drm_plane *plane, ...@@ -13389,8 +13400,7 @@ intel_legacy_cursor_update(struct drm_plane *plane,
old_plane_state->src_h != src_h || old_plane_state->src_h != src_h ||
old_plane_state->crtc_w != crtc_w || old_plane_state->crtc_w != crtc_w ||
old_plane_state->crtc_h != crtc_h || old_plane_state->crtc_h != crtc_h ||
!old_plane_state->visible || !old_plane_state->fb != !fb)
old_plane_state->fb->modifier != fb->modifier)
goto slow; goto slow;
new_plane_state = intel_plane_duplicate_state(plane); new_plane_state = intel_plane_duplicate_state(plane);
...@@ -13413,10 +13423,6 @@ intel_legacy_cursor_update(struct drm_plane *plane, ...@@ -13413,10 +13423,6 @@ intel_legacy_cursor_update(struct drm_plane *plane,
if (ret) if (ret)
goto out_free; goto out_free;
/* Visibility changed, must take slowpath. */
if (!new_plane_state->visible)
goto slow_free;
ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex); ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex);
if (ret) if (ret)
goto out_free; goto out_free;
...@@ -13456,9 +13462,12 @@ intel_legacy_cursor_update(struct drm_plane *plane, ...@@ -13456,9 +13462,12 @@ intel_legacy_cursor_update(struct drm_plane *plane,
new_plane_state->fb = old_fb; new_plane_state->fb = old_fb;
to_intel_plane_state(new_plane_state)->vma = old_vma; to_intel_plane_state(new_plane_state)->vma = old_vma;
if (plane->state->visible)
intel_plane->update_plane(plane, intel_plane->update_plane(plane,
to_intel_crtc_state(crtc->state), to_intel_crtc_state(crtc->state),
to_intel_plane_state(plane->state)); to_intel_plane_state(plane->state));
else
intel_plane->disable_plane(plane, crtc);
intel_cleanup_plane_fb(plane, new_plane_state); intel_cleanup_plane_fb(plane, new_plane_state);
...@@ -13468,8 +13477,6 @@ intel_legacy_cursor_update(struct drm_plane *plane, ...@@ -13468,8 +13477,6 @@ intel_legacy_cursor_update(struct drm_plane *plane,
intel_plane_destroy_state(plane, new_plane_state); intel_plane_destroy_state(plane, new_plane_state);
return ret; return ret;
slow_free:
intel_plane_destroy_state(plane, new_plane_state);
slow: slow:
return drm_atomic_helper_update_plane(plane, crtc, fb, return drm_atomic_helper_update_plane(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h, crtc_x, crtc_y, crtc_w, crtc_h,
......
...@@ -1841,20 +1841,24 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate, ...@@ -1841,20 +1841,24 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate,
const struct intel_plane_state *pstate, const struct intel_plane_state *pstate,
uint32_t mem_value) uint32_t mem_value)
{ {
/* int cpp;
* We treat the cursor plane as always-on for the purposes of watermark
* calculation. Until we have two-stage watermark programming merged,
* this is necessary to avoid flickering.
*/
int cpp = 4;
int width = pstate->base.visible ? pstate->base.crtc_w : 64;
if (!cstate->base.active) /*
* Treat cursor with fb as always visible since cursor updates
* can happen faster than the vrefresh rate, and the current
* watermark code doesn't handle that correctly. Cursor updates
* which set/clear the fb or change the cursor size are going
* to get throttled by intel_legacy_cursor_update() to work
* around this problem with the watermark code.
*/
if (!cstate->base.active || !pstate->base.fb)
return 0; return 0;
cpp = pstate->base.fb->format->cpp[0];
return ilk_wm_method2(cstate->pixel_rate, return ilk_wm_method2(cstate->pixel_rate,
cstate->base.adjusted_mode.crtc_htotal, cstate->base.adjusted_mode.crtc_htotal,
width, cpp, mem_value); pstate->base.crtc_w, cpp, mem_value);
} }
/* Only for WM_LP. */ /* Only for WM_LP. */
......
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