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,
+                             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;
+               }
+
+               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) {
+                       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