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
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;
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;
}
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;
if (ret ||
!intel_dp_dotclk_valid(display,
adjusted_mode->crtc_clock,
+ adjusted_mode->crtc_htotal,
+ 0,
num_joined_pipes))
dsc_needed = true;
}
}
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),
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;
}
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__ */
if (ret ||
!intel_dp_dotclk_valid(display,
adjusted_mode->clock,
+ adjusted_mode->htotal,
+ 0,
num_joined_pipes))
dsc_needed = true;
}
/* 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));
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;
}
*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;
*/
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;
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;
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)
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__ */