]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
drm/i915/dsb: Account for VRR properly in DSB scanline stuff
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Mon, 24 Jun 2024 19:10:25 +0000 (22:10 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 29 Aug 2024 11:54:03 +0000 (14:54 +0300)
When determining various scanlines for DSB use we should take into
account whether VRR is active at the time when the DSB uses said
scanline information. For now all DSB scanline usage occurs prior
to the actual commit, so we only need to care about the state of
VRR at that time.

I've decided to move intel_crtc_scanline_to_hw() in its entirety
to the DSB code as it will also need to know the actual state
of VRR in order to do its job 100% correctly.

TODO: figure out how much of this could be moved to some
      more generic place and perhaps be shared with the CPU
      vblank evasion code/etc...

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

index 9049b9a1209d87d6e43947df379300118ca8ea23..9ad0cb3fab298d55c4afa8efab2e50ea02a51f6d 100644 (file)
@@ -1032,8 +1032,8 @@ static bool intel_crtc_vrr_enabling(struct intel_atomic_state *state,
                  vrr_params_changed(old_crtc_state, new_crtc_state)));
 }
 
-static bool intel_crtc_vrr_disabling(struct intel_atomic_state *state,
-                                    struct intel_crtc *crtc)
+bool intel_crtc_vrr_disabling(struct intel_atomic_state *state,
+                             struct intel_crtc *crtc)
 {
        const struct intel_crtc_state *old_crtc_state =
                intel_atomic_get_old_crtc_state(state, crtc);
index b0cf6ca70952e1e4cd27840cc4555d6bdf625d3b..b21d9578d5db4d210391c83584b2a3c92b9d6e08 100644 (file)
@@ -532,6 +532,9 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state);
 
 void intel_update_watermarks(struct drm_i915_private *i915);
 
+bool intel_crtc_vrr_disabling(struct intel_atomic_state *state,
+                             struct intel_crtc *crtc);
+
 /* modesetting */
 int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
                                      const char *reason, u8 pipe_mask);
index 6ca052558e3bda4852ab4c566f5468e8002b06a1..2c7c21c69ad6ae90c87b88df88fa7b2c64f16b9d 100644 (file)
@@ -83,15 +83,72 @@ struct intel_dsb {
 #define DSB_OPCODE_POLL                        0xA
 /* see DSB_REG_VALUE_MASK */
 
-static int dsb_dewake_scanline(const struct intel_crtc_state *crtc_state)
+static bool pre_commit_is_vrr_active(struct intel_atomic_state *state,
+                                    struct intel_crtc *crtc)
 {
-       struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+       const struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       const struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+
+       /* VRR will be enabled afterwards, if necessary */
+       if (intel_crtc_needs_modeset(new_crtc_state))
+               return false;
+
+       /* VRR will have been disabled during intel_pre_plane_update() */
+       return old_crtc_state->vrr.enable && !intel_crtc_vrr_disabling(state, crtc);
+}
+
+static const struct intel_crtc_state *
+pre_commit_crtc_state(struct intel_atomic_state *state,
+                     struct intel_crtc *crtc)
+{
+       const struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       const struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+
+       /*
+        * During fastsets/etc. the transcoder is still
+        * running with the old timings at this point.
+        */
+       if (intel_crtc_needs_modeset(new_crtc_state))
+               return new_crtc_state;
+       else
+               return old_crtc_state;
+}
+
+static int dsb_vtotal(struct intel_atomic_state *state,
+                     struct intel_crtc *crtc)
+{
+       const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
+
+       if (pre_commit_is_vrr_active(state, crtc))
+               return crtc_state->vrr.vmax;
+       else
+               return intel_mode_vtotal(&crtc_state->hw.adjusted_mode);
+}
+
+static int dsb_dewake_scanline(struct intel_atomic_state *state,
+                              struct intel_crtc *crtc)
+{
+       const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
+       struct drm_i915_private *i915 = to_i915(state->base.dev);
        unsigned int latency = skl_watermark_max_latency(i915, 0);
 
        return intel_mode_vdisplay(&crtc_state->hw.adjusted_mode) -
                intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, latency);
 }
 
+static int dsb_scanline_to_hw(struct intel_atomic_state *state,
+                             struct intel_crtc *crtc, int scanline)
+{
+       const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
+       int vtotal = dsb_vtotal(state, crtc);
+
+       return (scanline + vtotal - intel_crtc_scanline_offset(crtc_state)) % vtotal;
+}
+
 static u32 dsb_chicken(struct intel_crtc *crtc)
 {
        if (crtc->mode_flags & I915_MODE_FLAG_VRR)
@@ -487,8 +544,6 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state,
                                    unsigned int max_cmds)
 {
        struct drm_i915_private *i915 = to_i915(state->base.dev);
-       const struct intel_crtc_state *crtc_state =
-               intel_atomic_get_new_crtc_state(state, crtc);
        intel_wakeref_t wakeref;
        struct intel_dsb *dsb;
        unsigned int size;
@@ -524,7 +579,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state,
        dsb->ins_start_offset = 0;
 
        dsb->hw_dewake_scanline =
-               intel_crtc_scanline_to_hw(crtc_state, dsb_dewake_scanline(crtc_state));
+               dsb_scanline_to_hw(state, crtc, dsb_dewake_scanline(state, crtc));
 
        return dsb;
 
index f337cde821985f7d7463590570f03ed9070711d9..0b7f2134e44131525dfdf00955702d3d86a7731c 100644 (file)
@@ -190,7 +190,7 @@ static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc)
        return scanline;
 }
 
-static int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state)
+int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state)
 {
        struct intel_display *display = to_intel_display(crtc_state);
        struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
@@ -284,14 +284,6 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
        return (position + vtotal + crtc->scanline_offset) % vtotal;
 }
 
-int intel_crtc_scanline_to_hw(const struct intel_crtc_state *crtc_state,
-                             int scanline)
-{
-       int vtotal = intel_mode_vtotal(&crtc_state->hw.adjusted_mode);
-
-       return (scanline + vtotal - intel_crtc_scanline_offset(crtc_state)) % vtotal;
-}
-
 /*
  * The uncore version of the spin lock functions is used to decide
  * whether we need to lock the uncore lock or not.  This is only
index 45a4a961aaabc590844e5fb4e43ec1448957283e..6d7336256982619073cb5ae84a48d3d1481a5264 100644 (file)
@@ -40,7 +40,6 @@ void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc);
 void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc);
 void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state,
                                      bool vrr_enable);
-int intel_crtc_scanline_to_hw(const struct intel_crtc_state *crtc_state,
-                             int scanline);
+int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state);
 
 #endif /* __INTEL_VBLANK_H__ */