96 lines
4.2 KiB
Diff
96 lines
4.2 KiB
Diff
diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
|
|
--- a/drivers/gpu/drm/i915/display/intel_cursor.c
|
|
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
|
|
@@ -536,7 +536,8 @@ static void i9xx_cursor_disable_sel_fetch_arm(struct intel_dsb *dsb,
|
|
struct intel_display *display = to_intel_display(plane);
|
|
enum pipe pipe = plane->pipe;
|
|
|
|
- if (!crtc_state->enable_psr2_sel_fetch)
|
|
+ if (!crtc_state->enable_psr2_sel_fetch &&
|
|
+ !crtc_state->clear_psr2_sel_fetch)
|
|
return;
|
|
|
|
intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), 0);
|
|
@@ -569,8 +570,10 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_dsb *dsb,
|
|
struct intel_display *display = to_intel_display(plane);
|
|
enum pipe pipe = plane->pipe;
|
|
|
|
- if (!crtc_state->enable_psr2_sel_fetch)
|
|
+ if (!crtc_state->enable_psr2_sel_fetch) {
|
|
+ i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state);
|
|
return;
|
|
+ }
|
|
|
|
if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) {
|
|
if (crtc_state->enable_psr2_su_region_et) {
|
|
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
|
|
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
|
|
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
|
|
@@ -1177,6 +1177,8 @@ struct intel_crtc_state {
|
|
bool has_sel_update;
|
|
bool enable_psr2_sel_fetch;
|
|
bool enable_psr2_su_region_et;
|
|
+ /* Drop the stale selective fetch enable bits as selective fetch is turned off */
|
|
+ bool clear_psr2_sel_fetch;
|
|
bool req_psr2_sdp_prior_scanline;
|
|
bool has_panel_replay;
|
|
bool link_off_after_as_sdp_when_pr_active;
|
|
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
|
|
--- a/drivers/gpu/drm/i915/display/intel_psr.c
|
|
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
|
|
@@ -2941,6 +2941,8 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
|
struct intel_crtc *crtc)
|
|
{
|
|
struct intel_display *display = to_intel_display(state);
|
|
+ const struct intel_crtc_state *old_crtc_state =
|
|
+ intel_atomic_get_old_crtc_state(state, crtc);
|
|
struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
|
|
struct intel_plane_state *new_plane_state, *old_plane_state;
|
|
struct intel_plane *plane;
|
|
@@ -2953,6 +2955,19 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
|
bool full_update = false, su_area_changed;
|
|
int i, ret;
|
|
|
|
+ /*
|
|
+ * Selective fetch is not always usable, for instance it is dropped
|
|
+ * while pipe CRC is active. The planes keep their selective fetch
|
|
+ * enable bit set in hardware over that, and a plane disabled while
|
|
+ * selective fetch is off never gets the bit cleared. Once selective
|
|
+ * fetch comes back the hardware would resume fetching for a plane that
|
|
+ * is no longer enabled and keep its DDB range reserved, so have the
|
|
+ * plane update drop the bit for every plane of the pipe as selective
|
|
+ * fetch is turned off.
|
|
+ */
|
|
+ crtc_state->clear_psr2_sel_fetch = old_crtc_state->enable_psr2_sel_fetch &&
|
|
+ !crtc_state->enable_psr2_sel_fetch;
|
|
+
|
|
if (!crtc_state->enable_psr2_sel_fetch)
|
|
return 0;
|
|
|
|
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
|
|
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
|
|
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
|
|
@@ -885,7 +885,8 @@ static void icl_plane_disable_sel_fetch_arm(struct intel_dsb *dsb,
|
|
struct intel_display *display = to_intel_display(plane);
|
|
enum pipe pipe = plane->pipe;
|
|
|
|
- if (!crtc_state->enable_psr2_sel_fetch)
|
|
+ if (!crtc_state->enable_psr2_sel_fetch &&
|
|
+ !crtc_state->clear_psr2_sel_fetch)
|
|
return;
|
|
|
|
intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0);
|
|
@@ -1634,10 +1635,8 @@ static void icl_plane_update_sel_fetch_arm(struct intel_dsb *dsb,
|
|
struct intel_display *display = to_intel_display(plane);
|
|
enum pipe pipe = plane->pipe;
|
|
|
|
- if (!crtc_state->enable_psr2_sel_fetch)
|
|
- return;
|
|
-
|
|
- if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0)
|
|
+ if (crtc_state->enable_psr2_sel_fetch &&
|
|
+ drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0)
|
|
intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id),
|
|
SEL_FETCH_PLANE_CTL_ENABLE);
|
|
else
|