]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/i915/display: use GOSUB to program double buffered LUT registers
authorChaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
Fri, 23 May 2025 06:20:38 +0000 (11:50 +0530)
committerAnimesh Manna <animesh.manna@intel.com>
Mon, 26 May 2025 07:48:16 +0000 (13:18 +0530)
With addition of double buffered GAMMA registers in PTL, we can now
program them in the active region. Use GOSUB instruction of DSB to
program them.

It is done in the following steps:
1. intel_color_prepare_commit()
- If the platform supports, prepare a dsb instance (dsb_color)
  hooked to DSB0.
- Add all the register write instructions to dsb_color through
  the load_lut() hook
                - Do not add the vrr_send_push() logic to the buffer as it
  should be taken care by dsb_commit instance of DSB0
                - Finish preparation of the buffer by aligning it to 64 bit

2. intel_atomic_dsb_finish()
- Add the gosub instruction into the dsb_commit instance of DSB0
  using intel_dsb_gosub()
- If needed, add the vrr_send_push() logic to dsb_commit after it

v2: Refactor code to simplify commit completion flow.
    Add some helpers along the way (Ville)
v3: s/doubled/double and add display to commit message prefix (Uma)

Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
Link: https://lore.kernel.org/r/20250523062041.166468-9-chaitanya.kumar.borah@intel.com
drivers/gpu/drm/i915/display/intel_color.c
drivers/gpu/drm/i915/display/intel_color.h
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display_device.h

index bb2da3a53e9ca1ac0946f76b698dd4e06289c081..ac00b86798fb5deaccfa1686835e0cb0d98c89a3 100644 (file)
@@ -1965,6 +1965,25 @@ void intel_color_modeset(const struct intel_crtc_state *crtc_state)
        }
 }
 
+bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state)
+{
+       return crtc_state->dsb_color;
+}
+
+bool intel_color_uses_chained_dsb(const struct intel_crtc_state *crtc_state)
+{
+       struct intel_display *display = to_intel_display(crtc_state);
+
+       return crtc_state->dsb_color && !HAS_DOUBLE_BUFFERED_LUT(display);
+}
+
+bool intel_color_uses_gosub_dsb(const struct intel_crtc_state *crtc_state)
+{
+       struct intel_display *display = to_intel_display(crtc_state);
+
+       return crtc_state->dsb_color && HAS_DOUBLE_BUFFERED_LUT(display);
+}
+
 void intel_color_prepare_commit(struct intel_atomic_state *state,
                                struct intel_crtc *crtc)
 {
@@ -1982,20 +2001,27 @@ void intel_color_prepare_commit(struct intel_atomic_state *state,
        if (!crtc_state->pre_csc_lut && !crtc_state->post_csc_lut)
                return;
 
-       crtc_state->dsb_color = intel_dsb_prepare(state, crtc, INTEL_DSB_1, 1024);
-       if (!crtc_state->dsb_color)
+       if (HAS_DOUBLE_BUFFERED_LUT(display))
+               crtc_state->dsb_color = intel_dsb_prepare(state, crtc, INTEL_DSB_0, 1024);
+       else
+               crtc_state->dsb_color = intel_dsb_prepare(state, crtc, INTEL_DSB_1, 1024);
+
+       if (!intel_color_uses_dsb(crtc_state))
                return;
 
        display->funcs.color->load_luts(crtc_state);
 
-       if (crtc_state->use_dsb) {
+       if (crtc_state->use_dsb && intel_color_uses_chained_dsb(crtc_state)) {
                intel_vrr_send_push(crtc_state->dsb_color, crtc_state);
                intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color);
                intel_vrr_check_push_sent(crtc_state->dsb_color, crtc_state);
                intel_dsb_interrupt(crtc_state->dsb_color);
        }
 
-       intel_dsb_finish(crtc_state->dsb_color);
+       if (intel_color_uses_gosub_dsb(crtc_state))
+               intel_dsb_gosub_finish(crtc_state->dsb_color);
+       else
+               intel_dsb_finish(crtc_state->dsb_color);
 }
 
 void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
@@ -2012,11 +2038,6 @@ void intel_color_wait_commit(const struct intel_crtc_state *crtc_state)
                intel_dsb_wait(crtc_state->dsb_color);
 }
 
-bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state)
-{
-       return crtc_state->dsb_color;
-}
-
 static bool intel_can_preload_luts(struct intel_atomic_state *state,
                                   struct intel_crtc *crtc)
 {
index 9d66457c1e893b572aaf8ee4e139105b37c23f6f..bf7a12ce9df0f809dbfa5f73f1dd8d510f90e4f9 100644 (file)
@@ -24,6 +24,8 @@ void intel_color_prepare_commit(struct intel_atomic_state *state,
                                struct intel_crtc *crtc);
 void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state);
 bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state);
+bool intel_color_uses_chained_dsb(const struct intel_crtc_state *crtc_state);
+bool intel_color_uses_gosub_dsb(const struct intel_crtc_state *crtc_state);
 void intel_color_wait_commit(const struct intel_crtc_state *crtc_state);
 void intel_color_commit_noarm(struct intel_dsb *dsb,
                              const struct intel_crtc_state *crtc_state);
index f261ceca5a3a5f2017c450880fdd67c9ce115101..128b2d865ac378bd49d2fd99e986896eba2edfea 100644 (file)
@@ -7238,20 +7238,24 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
                if (DISPLAY_VER(display) >= 9)
                        skl_detach_scalers(new_crtc_state->dsb_commit,
                                           new_crtc_state);
-
-               if (!new_crtc_state->dsb_color) {
-                       intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1);
-
-                       intel_vrr_send_push(new_crtc_state->dsb_commit, new_crtc_state);
-                       intel_dsb_wait_vblank_delay(state, new_crtc_state->dsb_commit);
-                       intel_vrr_check_push_sent(new_crtc_state->dsb_commit, new_crtc_state);
-                       intel_dsb_interrupt(new_crtc_state->dsb_commit);
-               }
        }
 
-       if (new_crtc_state->dsb_color)
+       if (intel_color_uses_chained_dsb(new_crtc_state))
                intel_dsb_chain(state, new_crtc_state->dsb_commit,
                                new_crtc_state->dsb_color, true);
+       else if (intel_color_uses_gosub_dsb(new_crtc_state))
+               intel_dsb_gosub(new_crtc_state->dsb_commit,
+                               new_crtc_state->dsb_color);
+
+       if (new_crtc_state->use_dsb && !intel_color_uses_chained_dsb(new_crtc_state)) {
+               intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1);
+
+               intel_vrr_send_push(new_crtc_state->dsb_commit, new_crtc_state);
+               intel_dsb_wait_vblank_delay(state, new_crtc_state->dsb_commit);
+               intel_vrr_check_push_sent(new_crtc_state->dsb_commit,
+                                         new_crtc_state);
+               intel_dsb_interrupt(new_crtc_state->dsb_commit);
+       }
 
        intel_dsb_finish(new_crtc_state->dsb_commit);
 }
index f0ea56cc5def5e7e4f56a87073bb9e749b31a6e8..0ac5484c004380d9d9563b54b3adddc21ac1669c 100644 (file)
@@ -157,6 +157,7 @@ struct intel_display_platforms {
 #define HAS_DMC(__display)             (DISPLAY_RUNTIME_INFO(__display)->has_dmc)
 #define HAS_DMC_WAKELOCK(__display)    (DISPLAY_VER(__display) >= 20)
 #define HAS_DOUBLE_BUFFERED_M_N(__display)     (DISPLAY_VER(__display) >= 9 || (__display)->platform.broadwell)
+#define HAS_DOUBLE_BUFFERED_LUT(__display)     (DISPLAY_VER(__display) >= 30)
 #define HAS_DOUBLE_WIDE(__display)     (DISPLAY_VER(__display) < 4)
 #define HAS_DP20(__display)            ((__display)->platform.dg2 || DISPLAY_VER(__display) >= 14)
 #define HAS_DPT(__display)             (DISPLAY_VER(__display) >= 13)