]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/i915/dsb: Move the DSB_PMCTRL* reset out of intel_dsb_finish()
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 12 Jun 2025 14:50:17 +0000 (17:50 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 17 Jun 2025 16:12:59 +0000 (19:12 +0300)
When using the flip queue, due to the DMC vs. DSB register corruption
problem, we must not issue any register writes from the DSB after
unhalting the DMC. Currently we are doing just that by trying to
restore DSB_PMCTRL* back to a sane state from intel_dsb_finish().

Since the only place left that pokes at DSB_PMCTRL* is intel_dsb_chain()
we can just do DSB_PMCTRL_2/DSB_FORCE_DEWAKE reset in the same place.

The DSB_PMCTRL reset is trickier since we'd have to do it from the
chained DSB itself. But based on my earlier testing
DSB_PMCTRL/DSB_ENABLE_DEWAKE doesn't actually do anything if the DSB
isn't actually enabled, so we can omit the reset to keep things a bit
simpler. We do need to reset DSB_PMCTRL/DSB_ENABLE_DEWAKE before
tarting the DSB however, in case it was left enabled from a previous
use.

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/20250612145018.8735-6-ville.syrjala@linux.intel.com
drivers/gpu/drm/i915/display/intel_dsb.c

index 2f7bd8da1bf1777a5f27b0429090fb33847399ac..aaa2a4a52edcfe537b5211f4189abf081cc4c3dd 100644 (file)
@@ -628,18 +628,6 @@ void intel_dsb_gosub_finish(struct intel_dsb *dsb)
 
 void intel_dsb_finish(struct intel_dsb *dsb)
 {
-       struct intel_crtc *crtc = dsb->crtc;
-
-       /*
-        * DSB_FORCE_DEWAKE remains active even after DSB is
-        * disabled, so make sure to clear it (if set during
-        * intel_dsb_commit()). And clear DSB_ENABLE_DEWAKE as
-        * well for good measure.
-        */
-       intel_dsb_reg_write(dsb, DSB_PMCTRL(crtc->pipe, dsb->id), 0);
-       intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(crtc->pipe, dsb->id),
-                                  DSB_FORCE_DEWAKE, 0);
-
        intel_dsb_align_tail(dsb);
 
        intel_dsb_buffer_flush_map(&dsb->dsb_buf);
@@ -780,6 +768,8 @@ static void _intel_dsb_chain(struct intel_atomic_state *state,
                intel_dsb_reg_write(dsb, DSB_PMCTRL(pipe, chained_dsb->id),
                                    DSB_ENABLE_DEWAKE |
                                    DSB_SCANLINE_FOR_DEWAKE(hw_dewake_scanline));
+       } else {
+               intel_dsb_reg_write(dsb, DSB_PMCTRL(pipe, chained_dsb->id), 0);
        }
 
        intel_dsb_reg_write(dsb, DSB_HEAD(pipe, chained_dsb->id),
@@ -801,6 +791,13 @@ static void _intel_dsb_chain(struct intel_atomic_state *state,
                intel_dsb_wait_scanline_out(state, dsb,
                                            dsb_dewake_scanline_start(state, crtc),
                                            dsb_dewake_scanline_end(state, crtc));
+
+               /*
+                * DSB_FORCE_DEWAKE remains active even after DSB is
+                * disabled, so make sure to clear it.
+                */
+               intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(crtc->pipe, dsb->id),
+                                          DSB_FORCE_DEWAKE, 0);
        }
 }
 
@@ -856,6 +853,8 @@ void intel_dsb_commit(struct intel_dsb *dsb)
                          dsb_error_int_status(display) | DSB_PROG_INT_STATUS |
                          dsb_error_int_en(display) | DSB_PROG_INT_EN);
 
+       intel_de_write_fw(display, DSB_PMCTRL(pipe, dsb->id), 0);
+
        intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id),
                          intel_dsb_head(dsb));