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);
+       }
+
+       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)
+               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

Reply via email to