From patchwork Fri Jul 11 10:50:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: drm/i915/display: WA_14011503117 From: Nemesa Garg X-Patchwork-Id: 663623 Message-Id: <20250711105021.1779920-1-nemesa.garg@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Cc: Nemesa Garg Date: Fri, 11 Jul 2025 16:20:21 +0530 Signed-off-by: Nemesa Garg --- drivers/gpu/drm/i915/display/intel_display.c | 22 +++++++++++-- .../drm/i915/display/intel_display_types.h | 2 ++ drivers/gpu/drm/i915/display/skl_scaler.c | 32 +++++++++++++++++++ drivers/gpu/drm/i915/display/skl_scaler.h | 5 +++ 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 456fc4b04cda..b5634d9112d9 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1695,17 +1695,26 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); + const struct intel_crtc_state *old_pipe_crtc_state = + intel_atomic_get_old_crtc_state(state, pipe_crtc); pipe_crtc->active = true; if (glk_need_scaler_clock_gating_wa(pipe_crtc_state)) glk_pipe_scaler_clock_gating_wa(pipe_crtc, true); + if (DISPLAY_VER(display) == 13) + skl_scaler_ecc_mask(state, pipe_crtc); + if (DISPLAY_VER(display) >= 9) skl_pfit_enable(pipe_crtc_state); else ilk_pfit_enable(pipe_crtc_state); + /* WA_14011503117: adlp_p */ + if (DISPLAY_VER(display) == 13) + skl_scaler_ecc_unmask(old_pipe_crtc_state, pipe_crtc_state); + /* * On ILK+ LUT must be loaded before the pipe is running but with * clocks enabled @@ -6563,7 +6572,8 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, } } -static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state, +static void intel_pipe_fastset(struct intel_atomic_state *state, + const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state) { struct intel_display *display = to_intel_display(new_crtc_state); @@ -6579,6 +6589,9 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state, */ intel_set_pipe_src_size(new_crtc_state); + if (DISPLAY_VER(display) == 13) + skl_scaler_ecc_mask(state, crtc); + /* on skylake this is done by detaching scalers */ if (DISPLAY_VER(display) >= 9) { if (new_crtc_state->pch_pfit.enabled) @@ -6590,6 +6603,11 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state, ilk_pfit_disable(old_crtc_state); } + /* WA_14011503117: adlp_p */ + + if (DISPLAY_VER(display) == 13) + skl_scaler_ecc_unmask(old_crtc_state, new_crtc_state); + /* * The register is supposedly single buffered so perhaps * not 100% correct to do this here. But SKL+ calculate @@ -6634,7 +6652,7 @@ static void commit_pipe_pre_planes(struct intel_atomic_state *state, bdw_set_pipe_misc(NULL, new_crtc_state); if (intel_crtc_needs_fastset(new_crtc_state)) - intel_pipe_fastset(old_crtc_state, new_crtc_state); + intel_pipe_fastset(state, old_crtc_state, new_crtc_state); } intel_psr2_program_trans_man_trk_ctl(NULL, new_crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index ce45261c4a8f..5bbd77661035 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -751,6 +751,8 @@ struct intel_crtc_scaler_state { /* scaler used by crtc for panel fitting purpose */ int scaler_id; + + bool scaler_ecc_masked; }; /* {crtc,crtc_state}->mode_flags */ diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index d77798499c57..beb0827bd46e 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -923,3 +923,35 @@ void skl_scaler_get_config(struct intel_crtc_state *crtc_state) else scaler_state->scaler_users &= ~(1 << SKL_CRTC_INDEX); } + +void skl_scaler_ecc_mask(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct intel_display *display = to_intel_display(state); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + struct intel_crtc_scaler_state *scaler_state = + &crtc_state->scaler_state; + + scaler_state->scaler_ecc_masked = true; + intel_de_write(display, XELPD_DISPLAY_ERR_FATAL_MASK, ~0); +} + +void skl_scaler_ecc_unmask(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + const struct intel_crtc_scaler_state *old_scaler_state = + &old_crtc_state->scaler_state; + const struct intel_crtc_scaler_state *new_scaler_state = + &crtc_state->scaler_state; + + int id = new_scaler_state->scaler_id; + + if (!old_scaler_state->scaler_ecc_masked && id != -1) + return; + + intel_de_write_fw(display, SKL_PS_ECC_STAT(crtc->pipe, id), 1); + intel_de_write(display, XELPD_DISPLAY_ERR_FATAL_MASK, 0); +} diff --git a/drivers/gpu/drm/i915/display/skl_scaler.h b/drivers/gpu/drm/i915/display/skl_scaler.h index 355ea15260ca..2a76ea5328c5 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.h +++ b/drivers/gpu/drm/i915/display/skl_scaler.h @@ -32,4 +32,9 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state); void skl_scaler_get_config(struct intel_crtc_state *crtc_state); +void skl_scaler_ecc_mask(struct intel_atomic_state *state, + struct intel_crtc *crtc); + +void skl_scaler_ecc_unmask(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *crtc_state); #endif