From: Ankit Nautiyal Date: Mon, 2 Feb 2026 10:37:28 +0000 (+0530) Subject: drm/i915/dp: Account for DSC slice overhead X-Git-Tag: v7.1-rc1~167^2~24^2~178 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5ec260d7bb47c8a63a6c8b31138a1a43f461d902;p=thirdparty%2Flinux.git drm/i915/dp: Account for DSC slice overhead 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 Reviewed-by: Imre Deak Link: https://patch.msgid.link/20260202103731.357416-15-ankit.k.nautiyal@intel.com --- diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 26917fe98ce3c..967a8b0a420c7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -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; } diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index edeb09372d1e7..95a38763a3679 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -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__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 83fe389ea2dcf..8bd3128add0ec 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -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; diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 642a89270d8ec..7e53201b3cb17 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -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) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h index aeb17670307b1..f4d5b37293cfc 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc.h @@ -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__ */