On Wed, Jan 21, 2026 at 09:23:21AM +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.
> 
> Signed-off-by: Ankit Nautiyal <[email protected]>
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c | 102 +++++++++++++++++++-----
>  1 file changed, 84 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index 02381f84fa58..d96d9ac1e830 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -2790,33 +2790,20 @@ 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_config(struct intel_encoder *encoder,

intel_dp_compute_link_for_joined_pipes(), similarly to the MST
counterpart?

> +                           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);
>       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 ||
> @@ -2879,6 +2866,85 @@ 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 ret = 0;
> +     int i;
> +
> +     if (crtc_state->fec_enable &&
> +         !intel_dp_supports_fec(intel_dp, connector, crtc_state))
> +             return -EINVAL;
> +
> +     for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
> +             enum joiner_type joiner = joiner_candidates[i];
> +             int max_dotclk = display->cdclk.max_dotclk_freq;
> +
> +             if (joiner == FORCED_JOINER) {
> +                     if (!connector->force_joined_pipes)
> +                             continue;
> +                     num_joined_pipes = connector->force_joined_pipes;
> +             } else {
> +                     num_joined_pipes = 1 << joiner;
> +             }
> +
> +             if ((joiner >= NO_JOINER && !intel_dp_has_joiner(intel_dp)) ||
> +                 (joiner == BIG_JOINER && !HAS_BIGJOINER(display)) ||
> +                 (joiner == ULTRA_JOINER && !HAS_ULTRAJOINER(display))) {
> +                     ret = -EINVAL;
> +                     break;

A simple loop over the number of possible joined pipes would be simpler
here as well, as in the mode_valid() function.

> +             }
> +
> +             if (adjusted_mode->hdisplay > num_joined_pipes * 
> intel_dp_hdisplay_limit(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_config(encoder, crtc_state, 
> conn_state,
> +                                                 respect_downstream_limits);
> +             if (ret)
> +                     continue;
> +
> +             max_dotclk *= num_joined_pipes;
> +
> +             if (adjusted_mode->crtc_clock <= max_dotclk) {

There seems to be a difference in the maximum dotclock for the DSC and
non-DSC modes, introduced later in the patchset. Since the non-DSC max
dotclock may be lower than the DSC one (oddly), there should be a
fallback to DSC mode for a given number of joined pipes if the non-DSC
mode is not possible with the same number of joined pipes because of the
mode specific dot clock limit. So the above check should be moved to
intel_dp_compute_link_for_joined_pipes() and performed for both the DSC
and non-DSC modes.

> +                     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
> 

Reply via email to