summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/display/intel_psr.c
diff options
context:
space:
mode:
authorJosé Roberto de Souza <jose.souza@intel.com>2021-09-29 17:14:05 -0700
committerJosé Roberto de Souza <jose.souza@intel.com>2021-09-30 15:04:44 -0700
commitef39826c12b409010b8fb29fc47e2586cd2635ee (patch)
treedd0528ef19b8ec71318bd0de672616584723870f /drivers/gpu/drm/i915/display/intel_psr.c
parent34ac6b651f39e63da8d0ae0edd2db32fbb1bc02c (diff)
downloadlinux-ef39826c12b409010b8fb29fc47e2586cd2635ee.tar.gz
linux-ef39826c12b409010b8fb29fc47e2586cd2635ee.tar.bz2
linux-ef39826c12b409010b8fb29fc47e2586cd2635ee.zip
drm/i915/display: Fix glitches when moving cursor with PSR2 selective fetch enabled
Legacy cursor APIs are handled by intel_legacy_cursor_update(), that calls drm_atomic_helper_update_plane() when going through the slow/atomic path to update cursor, what was the case for PSR2 selective fetch. drm_atomic_helper_update_plane() sets drm_atomic_state->legacy_cursor_update to true when updating the cursor plane, to allow several cursor updates to happen within the same frame, as userspace does that. If drivers waited for a vblank increment at the end of every cursor movement that would cause a visible lag in the cursor. But this optimization do not properly work with PSR2 selective fetch dirt area calculation, for example if within a single frame the cursor had 3 moves the final dirt area programmed to PSR2_MAN_TRK_CTL would be based in the second movement as old state and third movement as new state, not updating the area where cursor was in the first state. So here switching back to the fast path approach in intel_legacy_cursor_update() and handling cursor movements as frontbuffer rendering(psr_force_hw_tracking_exit()), that is not the most optimal for power-savings but is the solution that we have until mailbox style updates is implemented. Also removing the cursor workaround as not it is properly undestand the issue and is know that it will never cover all the cases. Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Acked-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20210930001409.254817-5-jose.souza@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_psr.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c59
1 files changed, 15 insertions, 44 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 9a5259bbebab..eddf4138b6a8 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1563,28 +1563,6 @@ static void intel_psr2_sel_fetch_pipe_alignment(const struct intel_crtc_state *c
}
/*
- * FIXME: Not sure why but when moving the cursor fast it causes some artifacts
- * of the cursor to be left in the cursor path, adding some pixels above the
- * cursor to the damaged area fixes the issue.
- */
-static void cursor_area_workaround(const struct intel_plane_state *new_plane_state,
- struct drm_rect *damaged_area,
- struct drm_rect *pipe_clip)
-{
- const struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane);
- int height;
-
- if (plane->id != PLANE_CURSOR)
- return;
-
- height = drm_rect_height(&new_plane_state->uapi.dst) / 2;
- damaged_area->y1 -= height;
- damaged_area->y1 = max(damaged_area->y1, 0);
-
- clip_area_update(pipe_clip, damaged_area);
-}
-
-/*
* TODO: Not clear how to handle planes with negative position,
* also planes are not updated if they have a negative X
* position so for now doing a full update in this cases
@@ -1684,9 +1662,6 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
damaged_area.y2 = new_plane_state->uapi.dst.y2;
clip_area_update(&pipe_clip, &damaged_area);
}
-
- cursor_area_workaround(new_plane_state, &damaged_area,
- &pipe_clip);
continue;
} else if (new_plane_state->uapi.alpha != old_plane_state->uapi.alpha) {
/* If alpha changed mark the whole plane area as damaged */
@@ -2120,20 +2095,16 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
/*
* When we will be completely rely on PSR2 S/W tracking in future,
* intel_psr_flush() will invalidate and flush the PSR for ORIGIN_FLIP
- * event also therefore tgl_dc3co_flush() require to be changed
+ * event also therefore tgl_dc3co_flush_locked() require to be changed
* accordingly in future.
*/
static void
-tgl_dc3co_flush(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
- enum fb_op_origin origin)
+tgl_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
+ enum fb_op_origin origin)
{
- mutex_lock(&intel_dp->psr.lock);
-
- if (!intel_dp->psr.dc3co_exitline)
- goto unlock;
-
- if (!intel_dp->psr.psr2_enabled || !intel_dp->psr.active)
- goto unlock;
+ if (!intel_dp->psr.dc3co_exitline || !intel_dp->psr.psr2_enabled ||
+ !intel_dp->psr.active)
+ return;
/*
* At every frontbuffer flush flip event modified delay of delayed work,
@@ -2141,14 +2112,11 @@ tgl_dc3co_flush(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
*/
if (!(frontbuffer_bits &
INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe)))
- goto unlock;
+ return;
tgl_psr2_enable_dc3co(intel_dp);
mod_delayed_work(system_wq, &intel_dp->psr.dc3co_work,
intel_dp->psr.dc3co_exit_delay);
-
-unlock:
- mutex_unlock(&intel_dp->psr.lock);
}
/**
@@ -2173,11 +2141,6 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
unsigned int pipe_frontbuffer_bits = frontbuffer_bits;
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- if (origin == ORIGIN_FLIP) {
- tgl_dc3co_flush(intel_dp, frontbuffer_bits, origin);
- continue;
- }
-
mutex_lock(&intel_dp->psr.lock);
if (!intel_dp->psr.enabled) {
mutex_unlock(&intel_dp->psr.lock);
@@ -2198,6 +2161,14 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
continue;
}
+ if (origin == ORIGIN_FLIP ||
+ (origin == ORIGIN_CURSOR_UPDATE &&
+ !intel_dp->psr.psr2_sel_fetch_enabled)) {
+ tgl_dc3co_flush_locked(intel_dp, frontbuffer_bits, origin);
+ mutex_unlock(&intel_dp->psr.lock);
+ continue;
+ }
+
/* By definition flush = invalidate + flush */
if (pipe_frontbuffer_bits)
psr_force_hw_tracking_exit(intel_dp);