On Wed, Jan 28, 2026 at 07:36:25PM +0530, Ankit Nautiyal wrote:
> 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;
When you make max_dotclk dependent on dsc vs. non-dsc mode later in the
patchset, this also needs to be checked for the non-dsc case as well
earlier in the function, falling back to dsc if crtc_clock is too high
for it (as for non-dsc max_dotclk may be lower than for dsc). I suppose
it's easier to move this check earlier already in this patch and later
change the error return to be a fallback, rechecking the clock for dsc
as well here.
> +
> 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;
> +
Even though num_pipes == 1 should always work, for clarity I initialize
ret to -EINVAL explicitly for the case where no pipes would work. Not
doing a fallback from a forced joined-pipe config would need this
anyway.
> + 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;
> + }
As in the previous patch, I'd just skip the force_joined_pipes &&
num_pipes != force_joined_pipes case.
> +
> + 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
>