diff options
| author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2025-06-24 20:00:46 +0300 |
|---|---|---|
| committer | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2025-06-27 15:55:47 +0300 |
| commit | a47828f3e7aaa9339f43c9a919c5b9b12b89d4b4 (patch) | |
| tree | a38f629a73c1b9e9a125550c8b5737e720670b0d | |
| parent | ec3a347beaa21b4a041f636b7081d17677fb3f56 (diff) | |
drm/i915/flipq: Implement Wa_18034343758
Implement the driver side of Wa_18034343758, which is supposed to
prevent the DSB and DMC from accessing registers in parallel, and
thus potentially corrupting the registers due to a hardware issue
(which should be fixed in PTL-B0).
The w/a sequence goes as follows:
DMC starts the DSB
| \
DMC halts itself | DSB waits a while for DMC to have time to halt
. | DSB executes normally
. | DSB unhalts the DMC at the very end
. /
DMC resumes execution
v2: PTL-B0+ firmware no longer has the w/a since the hw got fixed
v3: Do the w/a on all PTL for now since we only have the A0 firmware
binaries which issues the halt instructions unconditionally
v4: PTL DMC binaries do in fact have the A0 vs. B0 split, so skip
the w/a on PTL-B0+
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250624170049.27284-7-ville.syrjala@linux.intel.com
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_display.c | 8 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_flipq.c | 24 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_flipq.h | 2 |
3 files changed, 34 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 42780d7d8eed..456fc4b04cda 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7246,6 +7246,10 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state, } if (new_crtc_state->use_flipq || new_crtc_state->use_dsb) { + /* Wa_18034343758 */ + if (new_crtc_state->use_flipq) + intel_flipq_wait_dmc_halt(new_crtc_state->dsb_commit, crtc); + if (intel_crtc_needs_color_update(new_crtc_state)) intel_color_commit_noarm(new_crtc_state->dsb_commit, new_crtc_state); @@ -7276,6 +7280,10 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state, if (DISPLAY_VER(display) >= 9) skl_detach_scalers(new_crtc_state->dsb_commit, new_crtc_state); + + /* Wa_18034343758 */ + if (new_crtc_state->use_flipq) + intel_flipq_unhalt_dmc(new_crtc_state->dsb_commit, crtc); } if (intel_color_uses_chained_dsb(new_crtc_state)) diff --git a/drivers/gpu/drm/i915/display/intel_flipq.c b/drivers/gpu/drm/i915/display/intel_flipq.c index 9dbe0104c9ef..ee69b85cb104 100644 --- a/drivers/gpu/drm/i915/display/intel_flipq.c +++ b/drivers/gpu/drm/i915/display/intel_flipq.c @@ -400,3 +400,27 @@ void intel_flipq_add(struct intel_crtc *crtc, intel_flipq_sw_dmc_wake(crtc); } + +/* Wa_18034343758 */ +static bool need_dmc_halt_wa(struct intel_display *display) +{ + return DISPLAY_VER(display) == 20 || + (display->platform.pantherlake && + IS_DISPLAY_STEP(display, STEP_A0, STEP_B0)); +} + +void intel_flipq_wait_dmc_halt(struct intel_dsb *dsb, struct intel_crtc *crtc) +{ + struct intel_display *display = to_intel_display(crtc); + + if (need_dmc_halt_wa(display)) + intel_dsb_wait_usec(dsb, 2); +} + +void intel_flipq_unhalt_dmc(struct intel_dsb *dsb, struct intel_crtc *crtc) +{ + struct intel_display *display = to_intel_display(crtc); + + if (need_dmc_halt_wa(display)) + intel_dsb_reg_write(dsb, PIPEDMC_CTL(crtc->pipe), 0); +} diff --git a/drivers/gpu/drm/i915/display/intel_flipq.h b/drivers/gpu/drm/i915/display/intel_flipq.h index 195ff0dd83f5..2d4386a16197 100644 --- a/drivers/gpu/drm/i915/display/intel_flipq.h +++ b/drivers/gpu/drm/i915/display/intel_flipq.h @@ -29,5 +29,7 @@ void intel_flipq_add(struct intel_crtc *crtc, enum intel_dsb_id dsb_id, struct intel_dsb *dsb); int intel_flipq_exec_time_us(struct intel_display *display); +void intel_flipq_wait_dmc_halt(struct intel_dsb *dsb, struct intel_crtc *crtc); +void intel_flipq_unhalt_dmc(struct intel_dsb *dsb, struct intel_crtc *crtc); #endif /* __INTEL_FLIPQ_H__ */ |