Currently in intel_dp_mode_valid(), we compute the number of joined pipes required before deciding whether DSC is needed. This ordering prevents us from accounting for DSC-related overhead when determining pipe requirements.
Refactor the logic to start with a single pipe and incrementally try additional pipes only if needed. While DSC overhead is not yet computed here, this restructuring prepares the code to support that in a follow-up changes. Additionally, if a forced joiner configuration is present, we first check whether it satisfies the bandwidth and timing constraints. If it does not, we fall back to evaluating configurations with 1, 2, or 4 pipes joined and prune or keep the mode accordingly. Signed-off-by: Ankit Nautiyal <ankit.k.nauti...@intel.com> --- drivers/gpu/drm/i915/display/intel_dp.c | 79 +++++++++++++++++-------- 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0884826de1fd..0acd86c7d1c2 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1461,12 +1461,12 @@ intel_dp_mode_valid(struct drm_connector *_connector, { struct intel_display *display = to_intel_display(_connector->dev); struct intel_connector *connector = to_intel_connector(_connector); + int hdisplay_limit = DISPLAY_VER(display) >= 30 ? 6144 : 5120; struct intel_dp *intel_dp = intel_attached_dp(connector); enum intel_output_format sink_format, output_format; const struct drm_display_mode *fixed_mode; int target_clock = mode->clock; int max_rate, mode_rate, max_lanes, max_link_clock; - int max_dotclk = display->cdclk.max_dotclk_freq; u16 dsc_max_compressed_bpp = 0; u8 dsc_slice_count = 0; enum drm_mode_status status; @@ -1506,31 +1506,62 @@ intel_dp_mode_valid(struct drm_connector *_connector, mode_rate = intel_dp_link_required(target_clock, intel_dp_mode_min_output_bpp(connector, mode)); - num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector, - mode->hdisplay, target_clock); - max_dotclk *= num_joined_pipes; - - status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes); - if (status != MODE_OK) - return status; - - if (target_clock > max_dotclk) - return MODE_CLOCK_HIGH; - - if (intel_dp_has_dsc(connector)) { - get_dsc_slice_and_bpp(connector, mode, target_clock, - num_joined_pipes, - output_format, - max_link_clock, - max_lanes, - &dsc_max_compressed_bpp, - &dsc_slice_count); - - dsc = dsc_max_compressed_bpp && dsc_slice_count; + for (int joiner = -1; joiner <= 2; joiner++) { + int max_dotclk = display->cdclk.max_dotclk_freq; + + if (joiner == -1 && connector->force_joined_pipes) + num_joined_pipes = connector->force_joined_pipes; + else if (joiner == -1) + continue; + else + num_joined_pipes = 1 << joiner; + + if (joiner >= 0 && mode->hdisplay > num_joined_pipes * hdisplay_limit) { + status = MODE_CLOCK_HIGH; + continue; + } + + if ((num_joined_pipes == 4 && !HAS_ULTRAJOINER(display)) || + (num_joined_pipes == 2 && !HAS_BIGJOINER(display) && + !HAS_UNCOMPRESSED_JOINER(display))) { + status = MODE_CLOCK_HIGH; + continue; + } + + status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes); + if (status != MODE_OK) + continue; + + if (intel_dp_has_dsc(connector)) { + get_dsc_slice_and_bpp(connector, mode, target_clock, + num_joined_pipes, + output_format, + max_link_clock, + max_lanes, + &dsc_max_compressed_bpp, + &dsc_slice_count); + + dsc = dsc_max_compressed_bpp && dsc_slice_count; + } + + if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc) { + status = MODE_CLOCK_HIGH; + continue; + } + + max_dotclk *= num_joined_pipes; + + if (target_clock > max_dotclk) { + status = MODE_CLOCK_HIGH; + continue; + } + + status = MODE_OK; + break; } - if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc) - return MODE_CLOCK_HIGH; + if (status != MODE_OK || num_joined_pipes > 4) + return status; if (mode_rate > max_rate && !dsc) return MODE_CLOCK_HIGH; -- 2.45.2