Quoting Vinod Govindapillai (2026-01-05 07:48:58-03:00)
>For DG2, wa_22014263786 is applicable only if the number of active
>planes is greater than 1 in pipe A and pipe B. Cursor planes and
>any planes on pipe C or pipe D are not considered for this. As for
>DG2 this wa condition is based on the number of active planes, the
>check is moved to the fbc post plane update calls. The force slb
>invalidation chicken bit is set/unset based on the condition. For
>the other platforms where this wa is valid, the wa applied before
>enabling the FBC Unconditionally as before.
>
>v2: wrong version send as the initial patchset
> for DG2, active planes check should be done all pipes not just
> the FBC pipe (Matt)
>
>Bspec: 54077, 72197
>Signed-off-by: Vinod Govindapillai <[email protected]>
>---
> drivers/gpu/drm/i915/display/intel_fbc.c | 62 ++++++++++++++++++++++--
> 1 file changed, 59 insertions(+), 3 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c
>b/drivers/gpu/drm/i915/display/intel_fbc.c
>index 155b308ed66f..b01f9622510e 100644
>--- a/drivers/gpu/drm/i915/display/intel_fbc.c
>+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
>@@ -915,6 +915,15 @@ static void intel_fbc_program_cfb(struct intel_fbc *fbc)
> fbc->funcs->program_cfb(fbc);
> }
>
>+static void fbc_slb_invalidation_wa(struct intel_fbc *fbc,
>+ bool force_invalidation)
>+{
>+ u32 set = force_invalidation ? DPFC_CHICKEN_FORCE_SLB_INVALIDATION :
>0;
>+ u32 clear = force_invalidation ? 0 :
>DPFC_CHICKEN_FORCE_SLB_INVALIDATION;
>+
>+ intel_de_rmw(fbc->display, ILK_DPFC_CHICKEN(fbc->id), clear, set);
>+}
>+
> static void intel_fbc_program_workarounds(struct intel_fbc *fbc)
> {
> struct intel_display *display = fbc->display;
>@@ -946,10 +955,13 @@ static void intel_fbc_program_workarounds(struct
>intel_fbc *fbc)
> * Wa_22014263786
> * Fixes: Screen flicker with FBC and Package C state enabled
> * Workaround: Forced SLB invalidation before start of new frame.
>+ * For DG2, wa is applied only if the number of planes in
>+ * PIPE A and PIPE B is > 1. This wa criteria is assessed
>+ * seprately on every post plane update call to check if
>+ * the number of active planes condition is met.
> */
>- if (intel_display_wa(display, 22014263786))
>- intel_de_rmw(display, ILK_DPFC_CHICKEN(fbc->id),
>- 0, DPFC_CHICKEN_FORCE_SLB_INVALIDATION);
>+ if (intel_display_wa(display, 22014263786) && !display->platform.dg2)
>+ fbc_slb_invalidation_wa(fbc, true);
>
> /* wa_18038517565 Disable DPFC clock gating before FBC enable */
> if (display->platform.dg2 || DISPLAY_VER(display) >= 14)
>@@ -1887,13 +1899,57 @@ static void __intel_fbc_post_update(struct intel_fbc
>*fbc)
> intel_fbc_activate(fbc);
> }
>
>+static void
>+dg2_fbc_update_slb_invalidation(const struct intel_atomic_state *state)
>+{
>+ struct intel_display *display = to_intel_display(state);
>+ int i, num_active_planes = 0;
>+ struct intel_crtc_state *crtc_state;
>+ struct intel_crtc *crtc;
>+ enum intel_fbc_id fbc_id;
>+
>+ for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
>+ u8 active_planes;
>+
>+ if (crtc->pipe != PIPE_A && crtc->pipe != PIPE_B)
>+ continue;
>+
>+ active_planes = crtc_state->active_planes &
>~BIT(PLANE_CURSOR);
>+ num_active_planes += hweight8(active_planes);
I don't think this really counts the total number of active non-cursor
planes in pipes A and B. What if this display commit is for only one of
those pipes and the other one is already enabled with a non-zero
non-cursor plane?
>+ }
>+
>+ for_each_fbc_id(display, fbc_id) {
>+ struct intel_fbc *fbc = display->fbc.instances[fbc_id];
>+
>+ mutex_lock(&fbc->lock);
>+
>+ if (fbc->state.plane)
>+ fbc_slb_invalidation_wa(fbc, num_active_planes > 1);
>+
>+ mutex_unlock(&fbc->lock);
>+ }
>+}
>+
> void intel_fbc_post_update(struct intel_atomic_state *state,
> struct intel_crtc *crtc)
> {
>+ struct intel_display *display = to_intel_display(state);
> const struct intel_plane_state __maybe_unused *plane_state;
> struct intel_plane *plane;
> int i;
>
>+ /*
>+ * Wa_22014263786
>+ * Fixes: Screen flicker with FBC and Package C state enabled
>+ * Workaround: Forced SLB invalidation before start of new frame.
>+ * For DG2, wa is applied only if the number of planes in
>+ * PIPE A and PIPE B is > 1. This wa criteria is assessed
>+ * seprately on every post plane update call to check if
>+ * the number of active planes condition is met.
>+ */
>+ if (display->platform.dg2)
I think this should be
if (intel_display_wa(display, 22014263786) && display->platform.dg2)
, for consistency.
Also, we probably should drop one of the comments to avoid two
duplicated descriptions of the workaround; maybe drop this one.
--
Gustavo Sousa
>+ dg2_fbc_update_slb_invalidation(state);
>+
> for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
> struct intel_fbc *fbc = plane->fbc;
>
>--
>2.43.0
>