]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/i915/dp: Account for DSC slice overhead
authorAnkit Nautiyal <ankit.k.nautiyal@intel.com>
Mon, 2 Feb 2026 10:37:28 +0000 (16:07 +0530)
committerAnkit Nautiyal <ankit.k.nautiyal@intel.com>
Tue, 3 Feb 2026 08:17:11 +0000 (13:47 +0530)
Account for DSC slice overhead bubbles and adjust the pixel rate while
checking the pixel rate against the max dotclock limits.

v2: Add missing assignment for dsc_slice_count in
mst_connector_mode_valid_ctx(). (Imre)

v3: Explicitly pass dsc_slice_count as 0 for Non-DSC case. (Imre)

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Link: https://patch.msgid.link/20260202103731.357416-15-ankit.k.nautiyal@intel.com
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_dp.h
drivers/gpu/drm/i915/display/intel_dp_mst.c
drivers/gpu/drm/i915/display/intel_vdsc.c
drivers/gpu/drm/i915/display/intel_vdsc.h

index 26917fe98ce3c18fe9d99c260d88c9b11ecae0ee..967a8b0a420c7ed071806edee6611769dcf7e625 100644 (file)
@@ -1414,6 +1414,8 @@ bool intel_dp_can_join(struct intel_display *display,
 
 bool intel_dp_dotclk_valid(struct intel_display *display,
                           int target_clock,
+                          int htotal,
+                          int dsc_slice_count,
                           int num_joined_pipes)
 {
        int max_dotclk = display->cdclk.max_dotclk_freq;
@@ -1421,6 +1423,12 @@ bool intel_dp_dotclk_valid(struct intel_display *display,
 
        effective_dotclk_limit = max_dotclk * num_joined_pipes;
 
+       if (dsc_slice_count)
+               target_clock = intel_dsc_get_pixel_rate_with_dsc_bubbles(display,
+                                                                        target_clock,
+                                                                        htotal,
+                                                                        dsc_slice_count);
+
        return target_clock <= effective_dotclk_limit;
 }
 
@@ -1553,8 +1561,13 @@ intel_dp_mode_valid(struct drm_connector *_connector,
                if (status != MODE_OK)
                        continue;
 
+               if (!dsc)
+                       dsc_slice_count = 0;
+
                if (!intel_dp_dotclk_valid(display,
                                           target_clock,
+                                          mode->htotal,
+                                          dsc_slice_count,
                                           num_joined_pipes)) {
                        status = MODE_CLOCK_HIGH;
                        continue;
@@ -2816,6 +2829,8 @@ intel_dp_compute_link_for_joined_pipes(struct intel_encoder *encoder,
                if (ret ||
                    !intel_dp_dotclk_valid(display,
                                           adjusted_mode->crtc_clock,
+                                          adjusted_mode->crtc_htotal,
+                                          0,
                                           num_joined_pipes))
                        dsc_needed = true;
        }
@@ -2826,6 +2841,8 @@ intel_dp_compute_link_for_joined_pipes(struct intel_encoder *encoder,
        }
 
        if (dsc_needed) {
+               int dsc_slice_count;
+
                drm_dbg_kms(display->drm,
                            "Try DSC (fallback=%s, joiner=%s, force=%s)\n",
                            str_yes_no(ret), str_yes_no(joiner_needs_dsc),
@@ -2842,8 +2859,12 @@ intel_dp_compute_link_for_joined_pipes(struct intel_encoder *encoder,
                if (ret < 0)
                        return ret;
 
+               dsc_slice_count = intel_dsc_line_slice_count(&pipe_config->dsc.slice_config);
+
                if (!intel_dp_dotclk_valid(display,
                                           adjusted_mode->crtc_clock,
+                                          adjusted_mode->crtc_htotal,
+                                          dsc_slice_count,
                                           num_joined_pipes))
                        return -EINVAL;
        }
index edeb09372d1e7ed301ab13e7af28c0367fbe41de..95a38763a3679792abacb53a980589456f7d8fa2 100644 (file)
@@ -226,6 +226,8 @@ bool intel_dp_can_join(struct intel_display *display,
                       int num_joined_pipes);
 bool intel_dp_dotclk_valid(struct intel_display *display,
                           int target_clock,
+                          int htotal,
+                          int dsc_slice_count,
                           int num_joined_pipes);
 
 #endif /* __INTEL_DP_H__ */
index 83fe389ea2dcfa49633586d494b2e6996a421aff..8bd3128add0ecf6d1e444fd43eaa54c926eabb6c 100644 (file)
@@ -626,6 +626,8 @@ static int mst_stream_compute_link_for_joined_pipes(struct intel_encoder *encode
                if (ret ||
                    !intel_dp_dotclk_valid(display,
                                           adjusted_mode->clock,
+                                          adjusted_mode->htotal,
+                                          0,
                                           num_joined_pipes))
                        dsc_needed = true;
        }
@@ -637,6 +639,8 @@ static int mst_stream_compute_link_for_joined_pipes(struct intel_encoder *encode
 
        /* enable compression if the mode doesn't fit available BW */
        if (dsc_needed) {
+               int dsc_slice_count;
+
                drm_dbg_kms(display->drm, "Try DSC (fallback=%s, joiner=%s, force=%s)\n",
                            str_yes_no(ret), str_yes_no(joiner_needs_dsc),
                            str_yes_no(intel_dp->force_dsc_en));
@@ -670,8 +674,12 @@ static int mst_stream_compute_link_for_joined_pipes(struct intel_encoder *encode
                if (ret)
                        return ret;
 
+               dsc_slice_count = intel_dp_mst_dsc_get_slice_count(connector, pipe_config);
+
                if (!intel_dp_dotclk_valid(display,
                                           adjusted_mode->clock,
+                                          adjusted_mode->htotal,
+                                          dsc_slice_count,
                                           num_joined_pipes))
                        return -EINVAL;
        }
@@ -1528,6 +1536,8 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
 
        *status = MODE_CLOCK_HIGH;
        for (num_joined_pipes = 1; num_joined_pipes <= I915_MAX_PIPES; num_joined_pipes++) {
+               int dsc_slice_count = 0;
+
                if (connector->force_joined_pipes &&
                    num_joined_pipes != connector->force_joined_pipes)
                        continue;
@@ -1546,6 +1556,11 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
                         */
                        int pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
 
+                       dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
+                                                                      mode->clock,
+                                                                      mode->hdisplay,
+                                                                      num_joined_pipes);
+
                        if (!drm_dp_is_uhbr_rate(max_link_clock))
                                bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
 
@@ -1572,8 +1587,13 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
                if (*status != MODE_OK)
                        continue;
 
+               if (!dsc)
+                       dsc_slice_count = 0;
+
                if (!intel_dp_dotclk_valid(display,
                                           mode->clock,
+                                          mode->htotal,
+                                          dsc_slice_count,
                                           num_joined_pipes)) {
                        *status = MODE_CLOCK_HIGH;
                        continue;
index 642a89270d8ec83521a633b3d6e147299d5c7166..7e53201b3cb17d544a06fa4005bf5aba8102c0a6 100644 (file)
@@ -1104,7 +1104,6 @@ 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)
index aeb17670307b1b9c64404f8293b3b050c49e25d2..f4d5b37293cfc6f641cc59275ff512a1dd2622b8 100644 (file)
@@ -41,5 +41,8 @@ void intel_vdsc_state_dump(struct drm_printer *p, int indent,
                           const struct intel_crtc_state *crtc_state);
 int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state);
 unsigned int intel_vdsc_prefill_lines(const struct intel_crtc_state *crtc_state);
+int intel_dsc_get_pixel_rate_with_dsc_bubbles(struct intel_display *display,
+                                             int pixel_rate, int htotal,
+                                             int dsc_horizontal_slices);
 
 #endif /* __INTEL_VDSC_H__ */