199 lines
8.6 KiB
Diff
199 lines
8.6 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Gaggery Tsai <gaggery.tsai@intel.com>
|
|
Date: Tue, 28 Apr 2026 16:10:00 -0500
|
|
Subject: [PATCH] drm/i915: use TRANS_PUSH frame changes for Panel Replay
|
|
|
|
Panel Replay Selective Update requires a software-triggered Frame Change
|
|
event via TRANS_PUSH to send dirty regions to the panel. Cursor updates
|
|
can skip the normal VRR push path, so the panel may not receive cursor
|
|
position changes under Panel Replay SU.
|
|
|
|
Backport the upstream TRANS_PUSH frame-change flow for display 20+,
|
|
but keep it limited to Panel Replay for linux-ptl. Plain PSR2 must keep
|
|
using the old CURSURFLIVE frame-change path so systems still boot when
|
|
Panel Replay is disabled with xe.enable_panel_replay=0.
|
|
|
|
Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
|
|
---
|
|
drivers/gpu/drm/i915/display/intel_crtc.c | 4 +++-
|
|
drivers/gpu/drm/i915/display/intel_display_device.h | 1 +
|
|
drivers/gpu/drm/i915/display/intel_psr.c | 20 +++++++++++++++++---
|
|
drivers/gpu/drm/i915/display/intel_psr.h | 1 +
|
|
drivers/gpu/drm/i915/display/intel_vrr.c | 35 +++++++++++++++++++++++++++++------
|
|
drivers/gpu/drm/i915/display/intel_vrr.h | 1 +
|
|
drivers/gpu/drm/i915/display/intel_vrr_regs.h | 1 +
|
|
7 files changed, 53 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
|
|
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
|
|
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
|
|
@@ -747,7 +747,9 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
|
|
* push to affect the next frame instead of the current frame,
|
|
* which would cause the next frame to terminate already at vmin
|
|
* vblank start instead of vmax vblank start.
|
|
*/
|
|
- if (!state->base.legacy_cursor_update)
|
|
+ if (!state->base.legacy_cursor_update ||
|
|
+ (intel_psr_use_trans_push(new_crtc_state) &&
|
|
+ !new_crtc_state->vrr.enable))
|
|
intel_vrr_send_push(NULL, new_crtc_state);
|
|
|
|
local_irq_enable();
|
|
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
|
|
--- a/drivers/gpu/drm/i915/display/intel_display_device.h
|
|
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
|
|
@@ -186,6 +186,7 @@ struct intel_display_platforms {
|
|
#define HAS_PSR(__display) (DISPLAY_INFO(__display)->has_psr)
|
|
#define HAS_PSR_HW_TRACKING(__display) (DISPLAY_INFO(__display)->has_psr_hw_tracking)
|
|
#define HAS_PSR2_SEL_FETCH(__display) (DISPLAY_VER(__display) >= 12)
|
|
+#define HAS_PSR_TRANS_PUSH_FRAME_CHANGE(__display) (DISPLAY_VER(__display) >= 20)
|
|
#define HAS_SAGV(__display) (DISPLAY_VER(__display) >= 9 && \
|
|
!(__display)->platform.broxton && !(__display)->platform.geminilake)
|
|
#define HAS_TRANSCODER(__display, trans) ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
|
|
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
|
|
@@ -2130,5 +2130,8 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
|
|
|
|
intel_alpm_configure(intel_dp, crtc_state);
|
|
+
|
|
+ if (intel_psr_use_trans_push(crtc_state))
|
|
+ intel_vrr_psr_frame_change_enable(crtc_state);
|
|
}
|
|
|
|
static bool psr_interrupt_error_check(struct intel_dp *intel_dp)
|
|
@@ -2522,10 +2525,12 @@ void intel_psr_trigger_frame_change_event(struct intel_dsb *dsb,
|
|
const struct intel_crtc_state *crtc_state =
|
|
intel_pre_commit_crtc_state(state, crtc);
|
|
struct intel_display *display = to_intel_display(crtc);
|
|
|
|
- if (crtc_state->has_psr)
|
|
- intel_de_write_dsb(display, dsb,
|
|
- CURSURFLIVE(display, crtc->pipe), 0);
|
|
+ if (!crtc_state->has_psr || intel_psr_use_trans_push(crtc_state))
|
|
+ return;
|
|
+
|
|
+ intel_de_write_dsb(display, dsb,
|
|
+ CURSURFLIVE(display, crtc->pipe), 0);
|
|
}
|
|
|
|
/**
|
|
@@ -4615,3 +4620,10 @@ int intel_psr_min_guardband(struct intel_crtc_state *crtc_state)
|
|
|
|
return psr_min_guardband;
|
|
}
|
|
+
|
|
+bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state)
|
|
+{
|
|
+ struct intel_display *display = to_intel_display(crtc_state);
|
|
+
|
|
+ return HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display) && crtc_state->has_panel_replay;
|
|
+}
|
|
diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h
|
|
--- a/drivers/gpu/drm/i915/display/intel_psr.h
|
|
+++ b/drivers/gpu/drm/i915/display/intel_psr.h
|
|
@@ -80,5 +80,6 @@ bool intel_psr_needs_alpm_aux_less(struct intel_dp *intel_dp,
|
|
void intel_psr_compute_config_late(struct intel_dp *intel_dp,
|
|
struct intel_crtc_state *crtc_state);
|
|
int intel_psr_min_guardband(struct intel_crtc_state *crtc_state);
|
|
+bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state);
|
|
|
|
#endif /* __INTEL_PSR_H__ */
|
|
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
|
|
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
|
|
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
|
|
@@ -688,21 +688,40 @@ intel_vrr_dcb_reset(const struct intel_crtc_state *old_crtc_state,
|
|
intel_de_write(display, PIPEDMC_DCB_BALANCE_RESET(pipe), 0);
|
|
}
|
|
|
|
+static u32 trans_vrr_push(const struct intel_crtc_state *crtc_state,
|
|
+ bool send_push)
|
|
+{
|
|
+ struct intel_display *display = to_intel_display(crtc_state);
|
|
+ u32 trans_vrr_push = 0;
|
|
+
|
|
+ if (intel_vrr_always_use_vrr_tg(display) ||
|
|
+ crtc_state->vrr.enable)
|
|
+ trans_vrr_push |= TRANS_PUSH_EN;
|
|
+
|
|
+ if (send_push)
|
|
+ trans_vrr_push |= TRANS_PUSH_SEND;
|
|
+
|
|
+ if (intel_psr_use_trans_push(crtc_state))
|
|
+ trans_vrr_push |= LNL_TRANS_PUSH_PSR_PR_EN;
|
|
+
|
|
+ return trans_vrr_push;
|
|
+}
|
|
+
|
|
void intel_vrr_send_push(struct intel_dsb *dsb,
|
|
const struct intel_crtc_state *crtc_state)
|
|
{
|
|
struct intel_display *display = to_intel_display(crtc_state);
|
|
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
|
|
|
- if (!crtc_state->vrr.enable)
|
|
+ if (!crtc_state->vrr.enable && !intel_psr_use_trans_push(crtc_state))
|
|
return;
|
|
|
|
if (dsb)
|
|
intel_dsb_nonpost_start(dsb);
|
|
|
|
intel_de_write_dsb(display, dsb,
|
|
TRANS_PUSH(display, cpu_transcoder),
|
|
- TRANS_PUSH_EN | TRANS_PUSH_SEND);
|
|
+ trans_vrr_push(crtc_state, true));
|
|
|
|
if (dsb)
|
|
intel_dsb_nonpost_end(dsb);
|
|
@@ -888,7 +907,8 @@ static void intel_vrr_tg_enable(const struct intel_crtc_state *crtc_state,
|
|
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
|
u32 vrr_ctl;
|
|
|
|
- intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), TRANS_PUSH_EN);
|
|
+ intel_de_write(display, TRANS_PUSH(display, cpu_transcoder),
|
|
+ trans_vrr_push(crtc_state, false));
|
|
|
|
vrr_ctl = VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state);
|
|
|
|
@@ -919,1 +939,2 @@ static void intel_vrr_tg_disable(const struct intel_crtc_state *old_crtc_state)
|
|
- intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), 0);
|
|
+ intel_de_rmw(display, TRANS_PUSH(display, cpu_transcoder),
|
|
+ TRANS_PUSH_EN, 0);
|
|
@@ -970,6 +991,15 @@ void intel_vrr_transcoder_disable(const struct intel_crtc_state *old_crtc_state)
|
|
intel_vrr_tg_disable(old_crtc_state);
|
|
}
|
|
|
|
+void intel_vrr_psr_frame_change_enable(const struct intel_crtc_state *crtc_state)
|
|
+{
|
|
+ struct intel_display *display = to_intel_display(crtc_state);
|
|
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
|
+
|
|
+ intel_de_write(display, TRANS_PUSH(display, cpu_transcoder),
|
|
+ trans_vrr_push(crtc_state, false));
|
|
+}
|
|
+
|
|
bool intel_vrr_is_fixed_rr(const struct intel_crtc_state *crtc_state)
|
|
{
|
|
return crtc_state->vrr.flipline &&
|
|
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
|
|
--- a/drivers/gpu/drm/i915/display/intel_vrr.h
|
|
+++ b/drivers/gpu/drm/i915/display/intel_vrr.h
|
|
@@ -30,5 +30,6 @@ void intel_vrr_dcb_increment_flip_count(struct intel_crtc_state *crtc_state,
|
|
bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state);
|
|
void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state);
|
|
+void intel_vrr_psr_frame_change_enable(const struct intel_crtc_state *crtc_state);
|
|
void intel_vrr_get_config(struct intel_crtc_state *crtc_state);
|
|
int intel_vrr_vmax_vtotal(const struct intel_crtc_state *crtc_state);
|
|
int intel_vrr_vmin_vtotal(const struct intel_crtc_state *crtc_state);
|
|
diff --git a/drivers/gpu/drm/i915/display/intel_vrr_regs.h b/drivers/gpu/drm/i915/display/intel_vrr_regs.h
|
|
--- a/drivers/gpu/drm/i915/display/intel_vrr_regs.h
|
|
+++ b/drivers/gpu/drm/i915/display/intel_vrr_regs.h
|
|
@@ -163,6 +163,7 @@
|
|
#define TRANS_PUSH(display, trans) _MMIO_TRANS2((display), (trans), _TRANS_PUSH_A)
|
|
#define TRANS_PUSH_EN REG_BIT(31)
|
|
#define TRANS_PUSH_SEND REG_BIT(30)
|
|
+#define LNL_TRANS_PUSH_PSR_PR_EN REG_BIT(16)
|
|
|
|
#define _TRANS_VRR_VSYNC_A 0x60078
|
|
#define TRANS_VRR_VSYNC(display, trans) _MMIO_TRANS2((display), (trans), _TRANS_VRR_VSYNC_A)
|