Currently, the number of joined pipes are determined early in the flow, which limits flexibility for accounting DSC slice overhead. To address this, recompute the joined pipe count during DSC configuration.
Refactor intel_dp_dsc_compute_config() to iterate over joiner candidates and select the minimal joiner configuration that satisfies the mode requirements. This prepares the logic for future changes that will consider DSC slice overhead. v2: - Rename helper to intel_dp_compute_link_for_joined_pipes(). (Imre) - Move the check for max dotclock inside the helper so that if dotclock check fails for non DSC case for a given number of joined pipes, we are able to fallback to the DSC mode. (Imre) Signed-off-by: Ankit Nautiyal <[email protected]> --- drivers/gpu/drm/i915/display/intel_dp.c | 93 ++++++++++++++++++++----- 1 file changed, 77 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 599965a6e1a6..f8986f0acc79 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2804,33 +2804,23 @@ bool intel_dp_joiner_needs_dsc(struct intel_display *display, } static int -intel_dp_compute_link_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state, - bool respect_downstream_limits) +intel_dp_compute_link_for_joined_pipes(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state, + bool respect_downstream_limits) { struct intel_display *display = to_intel_display(encoder); - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config); struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + int max_dotclk = display->cdclk.max_dotclk_freq; struct link_config_limits limits; bool dsc_needed, joiner_needs_dsc; - int num_joined_pipes; int ret = 0; - if (pipe_config->fec_enable && - !intel_dp_supports_fec(intel_dp, connector, pipe_config)) - return -EINVAL; - - num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector, - adjusted_mode->crtc_hdisplay, - adjusted_mode->crtc_clock); - if (num_joined_pipes > 1) - pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, crtc->pipe); - joiner_needs_dsc = intel_dp_joiner_needs_dsc(display, num_joined_pipes); dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en || @@ -2880,6 +2870,11 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, return ret; } + max_dotclk *= num_joined_pipes; + + if (adjusted_mode->crtc_clock > max_dotclk) + return -EINVAL; + drm_dbg_kms(display->drm, "DP lane count %d clock %d bpp input %d compressed " FXP_Q4_FMT " link rate required %d available %d\n", pipe_config->lane_count, pipe_config->port_clock, @@ -2893,6 +2888,72 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, return 0; } +static int +intel_dp_compute_link_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + bool respect_downstream_limits) +{ + struct intel_display *display = to_intel_display(encoder); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_connector *connector = + to_intel_connector(conn_state->connector); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + int num_joined_pipes; + int num_pipes; + int ret = 0; + + if (crtc_state->fec_enable && + !intel_dp_supports_fec(intel_dp, connector, crtc_state)) + return -EINVAL; + + for (num_pipes = 0; num_pipes < I915_MAX_PIPES; num_pipes++) { + if (num_pipes == 0) { + if (!connector->force_joined_pipes) + continue; + num_joined_pipes = connector->force_joined_pipes; + } else { + num_joined_pipes = num_pipes; + } + + if (!intel_dp_can_join(display, num_joined_pipes)) + continue; + + if (adjusted_mode->hdisplay > + num_joined_pipes * intel_dp_max_hdisplay_per_pipe(display)) + continue; + + /* + * NOTE: + * The crtc_state->joiner_pipes should have been set at the end + * only if all the conditions are met. However that would mean + * that num_joined_pipes is passed around to all helpers and + * make them use it instead of using crtc_state->joiner_pipes + * directly or indirectly (via intel_crtc_num_joined_pipes()). + * + * For now, setting crtc_state->joiner_pipes to the candidate + * value to avoid the above churn and resetting it to 0, in case + * no joiner candidate is found to be suitable for the given + * configuration. + */ + if (num_joined_pipes > 1) + crtc_state->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, + crtc->pipe); + + ret = intel_dp_compute_link_for_joined_pipes(encoder, crtc_state, conn_state, + respect_downstream_limits); + if (ret == 0) + break; + } + + if (ret < 0) + crtc_state->joiner_pipes = 0; + + return ret; +} + bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { -- 2.45.2
