On Wed, 2026-07-01 at 18:31 +0300, Imre Deak wrote:
> Use the link caps configuration mask when applying DP compliance test
> link parameters during state computation.
> 
> Preserve the legacy behavior of falling back to all configurations with
> the requested lane count if the requested rate and lane count pair is
> not allowed.
> 
> In case no valid configuration is found fail the modeset.
> 
> v2:
> - Rebase on changes using a filter object instead of a mask of
>   configuration indices.
> - Rebase on changes using an iteration object.
> 
> Signed-off-by: Imre Deak <[email protected]>
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c      |  3 +-
>  drivers/gpu/drm/i915/display/intel_dp_test.c | 96 +++++++++++++++++++-
>  drivers/gpu/drm/i915/display/intel_dp_test.h |  3 +-
>  3 files changed, 99 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index b10bbbf0f49bf..42bb1c7622525 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -2808,7 +2808,8 @@ intel_dp_compute_config_limits(struct intel_dp 
> *intel_dp,
>               limits->link_config_filter = new_filter;
>       }
>  
> -     intel_dp_test_compute_config(intel_dp, crtc_state, limits);
> +     if (!intel_dp_test_compute_config(connector, crtc_state, limits))
> +             return false;
>  
>       return intel_dp_compute_config_link_bpp_limits(connector,
>                                                      crtc_state,
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_test.c 
> b/drivers/gpu/drm/i915/display/intel_dp_test.c
> index da7632536dace..ec7fa690910bb 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_test.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_test.c
> @@ -28,11 +28,92 @@ void intel_dp_test_reset(struct intel_dp *intel_dp)
>       memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance));
>  }
>  
> +static bool set_filter_for_lane_count(struct intel_connector *connector,
> +                                   struct intel_dp_link_caps *link_caps,
> +                                   int lane_count,
> +                                   struct link_config_limits *limits)
> +{
> +     struct intel_dp_link_config link_config;
> +     struct intel_dp_link_caps_order order =
> +             intel_dp_link_caps_connector_compute_order(connector);
> +     struct intel_dp_link_caps_filter new_filter = 
> INTEL_DP_LINK_CAPS_FILTER_NONE;
> +     struct intel_dp_link_caps_iter iter;
> +     bool found = false;
> +
> +     intel_dp_link_caps_iter_start(&iter, link_caps, order, 
> limits->link_config_filter);
> +     for_each_dp_link_config(&iter, &link_config) {
> +             if (link_config.lane_count != lane_count)
> +                     continue;
> +
> +             intel_dp_link_caps_filter_add(link_caps, &new_filter, 
> &link_config);
> +             found = true;
> +     }
> +     intel_dp_link_caps_iter_end(&iter);
> +
> +     if (!found)
> +             return false;
> +
> +     limits->link_config_filter = new_filter;
> +
> +     return true;
> +}
> +
> +static bool set_filter_for_link_config(struct intel_connector *connector,
> +                                    struct intel_dp_link_caps *link_caps,
> +                                    const struct intel_dp_link_config 
> *link_params,
> +                                    struct link_config_limits *limits)
> +{
> +     struct intel_dp_link_caps_filter new_filter = 
> INTEL_DP_LINK_CAPS_FILTER_NONE;
> +
> +     if (!intel_dp_link_caps_filter_add(link_caps, &new_filter, link_params))
> +             return false;
> +
> +     limits->link_config_filter = new_filter;
> +
> +     return true;
> +}
> +
> +static bool set_filter_for_link_params(struct intel_connector *connector,
> +                                    int link_rate, int lane_count,
> +                                    struct link_config_limits *limits)
> +{
> +     struct intel_dp *intel_dp = intel_attached_dp(connector);
> +     struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> +     struct intel_dp_link_caps *link_caps = intel_dp->link.caps;
> +     struct intel_display *display = to_intel_display(intel_dp);
> +     struct intel_dp_link_config requested_config;
> +
> +     requested_config.rate = link_rate;
> +     requested_config.lane_count = lane_count;
> +
> +     if (set_filter_for_link_config(connector, link_caps, &requested_config, 
> limits))
> +             return true;
> +
> +     /*
> +      * Preserve the legacy behavior: if the requested (rate, lane_count)
> +      * combination is not an allowed config, fall back to all configs
> +      * matching the requested lane count.
> +      *
> +      * TODO: Recheck whether this behavior is actually correct.
> +      */
> +     if (set_filter_for_lane_count(connector, link_caps, lane_count, limits))
> +             return true;
> +
> +     drm_dbg_kms(display->drm,
> +                 "[ENCODER:%d:%s] Invalid autotest link config parameters: 
> %dx%d\n",
> +                 encoder->base.base.id, encoder->base.name,
> +                 requested_config.lane_count,
> +                 requested_config.rate);
> +
> +     return false;
> +}
> +
>  /* Adjust link config limits based on compliance test requests. */
> -void intel_dp_test_compute_config(struct intel_dp *intel_dp,
> +bool intel_dp_test_compute_config(struct intel_connector *connector,
>                                 struct intel_crtc_state *pipe_config,
>                                 struct link_config_limits *limits)
>  {
> +     struct intel_dp *intel_dp = intel_attached_dp(connector);
>       struct intel_dp_link_caps *link_caps = intel_dp->link.caps;
>       struct intel_display *display = to_intel_display(intel_dp);
>  
> @@ -51,6 +132,11 @@ void intel_dp_test_compute_config(struct intel_dp 
> *intel_dp,
>       if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
>               int index;
>  
> +             /*
> +              * TODO: Remove the following min/max link limit setup
> +              * after converting to use the link configuration filter
> +              * instead in limits.
> +              */
>               /* Validate the compliance test data since max values
>                * might have changed due to link train fallback.
>                */
> @@ -65,7 +151,15 @@ void intel_dp_test_compute_config(struct intel_dp 
> *intel_dp,
>                       limits->min_lane_count = 
> intel_dp->compliance.test_lane_count;
>                       limits->max_lane_count = 
> intel_dp->compliance.test_lane_count;
>               }
> +
> +             if (!set_filter_for_link_params(connector,
> +                                             
> intel_dp->compliance.test_link_rate,
> +                                             
> intel_dp->compliance.test_lane_count,
> +                                             limits))
> +                     return false;
>       }
> +
> +     return true;
>  }
>  
>  /* Compliance test status bits  */
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_test.h 
> b/drivers/gpu/drm/i915/display/intel_dp_test.h
> index dcc167e4c7f65..a08f37a63dc9a 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_test.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp_test.h
> @@ -6,6 +6,7 @@
>  
>  #include <linux/types.h>
>  
> +struct intel_connector;
>  struct intel_crtc_state;
>  struct intel_display;
>  struct intel_dp;
> @@ -13,7 +14,7 @@ struct link_config_limits;
>  
>  void intel_dp_test_reset(struct intel_dp *intel_dp);
>  void intel_dp_test_request(struct intel_dp *intel_dp);
> -void intel_dp_test_compute_config(struct intel_dp *intel_dp,
> +bool intel_dp_test_compute_config(struct intel_connector *connector,
>                                 struct intel_crtc_state *pipe_config,
>                                 struct link_config_limits *limits);
>  bool intel_dp_test_phy(struct intel_dp *intel_dp);

Reviewed-by: Luca Coelho <[email protected]>

--
Cheers,
Luca.

Reply via email to