]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/i915/dsb: Introduce intel_dsb_vblank_evade()
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Mon, 30 Sep 2024 17:04:07 +0000 (20:04 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 3 Oct 2024 21:33:06 +0000 (00:33 +0300)
Add a helper for performing vblank evasion on the DSB. DSB based
plane updates will need this to guarantee all the double buffered
arming registers will get programmed atomically within the same
frame.

With VRR we more or less have two vblanks to worry about:
- vmax vblank start in case no push was sent
- vmin vblank start in case a push was already sent during
  the vertical active. Only a concern for mailbox updates,
  which I suppose could happen if the legacy cursor updates
  take the non-fastpath without setting
  state->legacy_cursor_update to false.
Since we don't know which case is relevant we'll just evade
both.

We must also make sure to evade both the delayed vblank
(for pipe/plane registers) and the undelayed vblank
(for transcoder registers and chained DSBs w/
DSB_WAIT_FOR_VBLANK).

TODO: come up with a sensible usec number for the evasion...

Reviewed-by: Animesh Manna <animesh.manna@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240930170415.23841-6-ville.syrjala@linux.intel.com
drivers/gpu/drm/i915/display/intel_dsb.c
drivers/gpu/drm/i915/display/intel_dsb.h

index 8514d721914007ade5c8cea6b43cd88f510c71fd..9ed7b03c1e33e59ccacd6f98f163b3f7b8a16ebb 100644 (file)
@@ -128,6 +128,12 @@ pre_commit_crtc_state(struct intel_atomic_state *state,
                return old_crtc_state;
 }
 
+static int dsb_vblank_delay(const struct intel_crtc_state *crtc_state)
+{
+       return intel_mode_vblank_start(&crtc_state->hw.adjusted_mode) -
+               intel_mode_vdisplay(&crtc_state->hw.adjusted_mode);
+}
+
 static int dsb_vtotal(struct intel_atomic_state *state,
                      struct intel_crtc *crtc)
 {
@@ -527,6 +533,31 @@ static u32 dsb_error_int_en(struct intel_display *display)
        return errors;
 }
 
+void intel_dsb_vblank_evade(struct intel_atomic_state *state,
+                           struct intel_dsb *dsb)
+{
+       struct intel_crtc *crtc = dsb->crtc;
+       const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
+       /* FIXME calibrate sensibly */
+       int latency = intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, 20);
+       int vblank_delay = dsb_vblank_delay(crtc_state);
+       int start, end;
+
+       if (pre_commit_is_vrr_active(state, crtc)) {
+               end = intel_vrr_vmin_vblank_start(crtc_state);
+               start = end - vblank_delay - latency;
+               intel_dsb_wait_scanline_out(state, dsb, start, end);
+
+               end = intel_vrr_vmax_vblank_start(crtc_state);
+               start = end - vblank_delay - latency;
+               intel_dsb_wait_scanline_out(state, dsb, start, end);
+       } else {
+               end = intel_mode_vblank_start(&crtc_state->hw.adjusted_mode);
+               start = end - vblank_delay - latency;
+               intel_dsb_wait_scanline_out(state, dsb, start, end);
+       }
+}
+
 static void _intel_dsb_chain(struct intel_atomic_state *state,
                             struct intel_dsb *dsb,
                             struct intel_dsb *chained_dsb,
index ff3b89dfffc1c35518d5ebefcd04508a90762f29..cce5cb1c60714fbdc87e4ba24d5491a11ec51ed6 100644 (file)
@@ -46,6 +46,8 @@ void intel_dsb_wait_scanline_in(struct intel_atomic_state *state,
 void intel_dsb_wait_scanline_out(struct intel_atomic_state *state,
                                 struct intel_dsb *dsb,
                                 int lower, int upper);
+void intel_dsb_vblank_evade(struct intel_atomic_state *state,
+                           struct intel_dsb *dsb);
 void intel_dsb_chain(struct intel_atomic_state *state,
                     struct intel_dsb *dsb,
                     struct intel_dsb *chained_dsb,