]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/i915/vdsc: Account for DSC slice overhead in intel_vdsc_min_cdclk()
authorAnkit Nautiyal <ankit.k.nautiyal@intel.com>
Tue, 23 Dec 2025 15:08:26 +0000 (20:38 +0530)
committerAnkit Nautiyal <ankit.k.nautiyal@intel.com>
Mon, 29 Dec 2025 05:17:41 +0000 (10:47 +0530)
When DSC is enabled on a pipe, the pipe pixel rate input to the
CDCLK frequency and pipe joining calculation needs an adjustment to
account for compression overhead "bubbles" added at each horizontal
slice boundary.

Account for this overhead while computing min cdclk required for DSC.

v2:
 - Get rid of the scaling factor and return unchanged pixel-rate
   instead of 0.
v3:
 - Use mul_u32_u32() for the bubble-adjusted pixel rate to avoid 64x64
   multiplication and drop redundant casts in DIV_ROUND_UP_ULL(). (Imre)

Bspec:68912
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Link: https://patch.msgid.link/20251223150826.2591182-1-ankit.k.nautiyal@intel.com
drivers/gpu/drm/i915/display/intel_vdsc.c

index ad5fe841e4b321cd38d0c507202e10b1f313dbac..5493082f30a75d873d9b12e0c6c917f13759fa32 100644 (file)
@@ -1050,15 +1050,40 @@ void intel_vdsc_state_dump(struct drm_printer *p, int indent,
        drm_dsc_dump_config(p, indent, &crtc_state->dsc.config);
 }
 
+static
+int intel_dsc_get_pixel_rate_with_dsc_bubbles(struct intel_display *display,
+                                             int pixel_rate, int htotal,
+                                             int dsc_horizontal_slices)
+{
+       int dsc_slice_bubbles;
+       u64 num;
+
+       if (drm_WARN_ON(display->drm, !htotal))
+               return pixel_rate;
+
+       dsc_slice_bubbles = 14 * dsc_horizontal_slices;
+       num = mul_u32_u32(pixel_rate, (htotal + dsc_slice_bubbles));
+
+       return DIV_ROUND_UP_ULL(num, htotal);
+}
+
 int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state)
 {
        struct intel_display *display = to_intel_display(crtc_state);
        int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
+       int htotal = crtc_state->hw.adjusted_mode.crtc_htotal;
+       int dsc_slices = crtc_state->dsc.slice_count;
+       int pixel_rate;
        int min_cdclk;
 
        if (!crtc_state->dsc.compression_enable)
                return 0;
 
+       pixel_rate = intel_dsc_get_pixel_rate_with_dsc_bubbles(display,
+                                                              crtc_state->pixel_rate,
+                                                              htotal,
+                                                              dsc_slices);
+
        /*
         * When we decide to use only one VDSC engine, since
         * each VDSC operates with 1 ppc throughput, pixel clock
@@ -1066,7 +1091,7 @@ int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state)
         * If there 2 VDSC engines, then pixel clock can't be higher than
         * VDSC clock(cdclk) * 2 and so on.
         */
-       min_cdclk = DIV_ROUND_UP(crtc_state->pixel_rate, num_vdsc_instances);
+       min_cdclk = DIV_ROUND_UP(pixel_rate, num_vdsc_instances);
 
        if (crtc_state->joiner_pipes) {
                int pixel_clock = intel_dp_mode_to_fec_clock(crtc_state->hw.adjusted_mode.clock);
@@ -1084,9 +1109,11 @@ int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state)
                 * => CDCLK >= compressed_bpp * Pixel clock  / 2 * Bigjoiner Interface bits
                 */
                int bigjoiner_interface_bits = DISPLAY_VER(display) >= 14 ? 36 : 24;
-               int min_cdclk_bj =
-                       (fxp_q4_to_int_roundup(crtc_state->dsc.compressed_bpp_x16) *
-                        pixel_clock) / (2 * bigjoiner_interface_bits);
+               int adjusted_pixel_rate =
+                       intel_dsc_get_pixel_rate_with_dsc_bubbles(display, pixel_clock,
+                                                                 htotal, dsc_slices);
+               int min_cdclk_bj = (fxp_q4_to_int_roundup(crtc_state->dsc.compressed_bpp_x16) *
+                                  adjusted_pixel_rate) / (2 * bigjoiner_interface_bits);
 
                min_cdclk = max(min_cdclk, min_cdclk_bj);
        }