Re: [RFC 1/4] drm/i915/display/dp: Add DP fallback on LT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 06 Feb 2024, Arun R Murthy <arun.r.murthy@xxxxxxxxx> wrote:
> Fallback mandates on DP link training failure. This patch just covers
> the DP2.0 fallback sequence.
>
> TODO: Need to implement the DP1.4 fallback.
>
> Signed-off-by: Arun R Murthy <arun.r.murthy@xxxxxxxxx>
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c | 92 ++++++++++++++++++++++---
>  1 file changed, 82 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 10ec231acd98..82d354a6b0cd 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -104,6 +104,50 @@ static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15};
>   */
>  static const u8 valid_dsc_slicecount[] = {1, 2, 4};
>  
> +/* DL Link Rates */
> +#define UHBR20		2000000
> +#define UHBR13P5	1350000
> +#define UHBR10		1000000
> +#define HBR3		810000
> +#define HBR2		540000
> +#define HBR		270000
> +#define RBR		162000
> +
> +/* DP Lane Count */
> +#define LANE_COUNT_4	4
> +#define LANE_COUNT_2	2
> +#define LANE_COUNT_1	1
> +
> +/* DP2.0 fallback values */
> +struct dp_fallback {
> +	u32 link_rate;
> +	u8 lane_count;
> +};
> +
> +struct dp_fallback dp2dot0_fallback[] = {
> +	{UHBR20, LANE_COUNT_4},
> +	{UHBR13P5, LANE_COUNT_4},
> +	{UHBR20, LANE_COUNT_2},
> +	{UHBR10, LANE_COUNT_4},
> +	{UHBR13P5, LANE_COUNT_2},
> +	{HBR3, LANE_COUNT_4},
> +	{UHBR20, LANE_COUNT_1},
> +	{UHBR10, LANE_COUNT_2},
> +	{HBR2, LANE_COUNT_4},
> +	{UHBR13P5, LANE_COUNT_1},
> +	{HBR3, LANE_COUNT_2},
> +	{UHBR10, LANE_COUNT_1},
> +	{HBR2, LANE_COUNT_2},
> +	{HBR, LANE_COUNT_4},
> +	{HBR3, LANE_COUNT_1},
> +	{RBR, LANE_COUNT_4},
> +	{HBR2, LANE_COUNT_1},
> +	{HBR, LANE_COUNT_2},
> +	{RBR, LANE_COUNT_2},
> +	{HBR, LANE_COUNT_1},
> +	{RBR, LANE_COUNT_1},
> +};
> +
>  /**
>   * intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or PCH)
>   * @intel_dp: DP struct
> @@ -299,6 +343,19 @@ static int intel_dp_common_len_rate_limit(const struct intel_dp *intel_dp,
>  				       intel_dp->num_common_rates, max_rate);
>  }
>  
> +static bool intel_dp_link_rate_supported(struct intel_dp *intel_dp, u32 link_rate)
> +{
> +	u8 i;
> +
> +	for (i = 0; i < ARRAY_SIZE(intel_dp->common_rates); i++) {
> +		if (intel_dp->common_rates[i] == link_rate)
> +			return true;
> +		else
> +			continue;
> +	}
> +	return false;
> +}
> +
>  static int intel_dp_common_rate(struct intel_dp *intel_dp, int index)
>  {
>  	if (drm_WARN_ON(&dp_to_i915(intel_dp)->drm,
> @@ -671,15 +728,6 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
>  	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
>  	int index;
>  
> -	/*
> -	 * TODO: Enable fallback on MST links once MST link compute can handle
> -	 * the fallback params.
> -	 */
> -	if (intel_dp->is_mst) {
> -		drm_err(&i915->drm, "Link Training Unsuccessful\n");
> -		return -1;
> -	}
> -

By removing this, the claim is both 8b/10b and 128b/132b DP MST link
training fallbacks work...

>  	if (intel_dp_is_edp(intel_dp) && !intel_dp->use_max_params) {
>  		drm_dbg_kms(&i915->drm,
>  			    "Retrying Link training for eDP with max parameters\n");
> @@ -687,6 +735,31 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
>  		return 0;
>  	}
>  
> +	/* DP fallback values */
> +	if (intel_dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_128B132B) {

...but this only addresses 128b/132b, and the 8b/10b MST drops to the
existing SST fallback path.

And with the current code, DP_CAP_ANSI_128B132B does not decide whether
we use DP MST or not. So this will also cover 8b/10b fallback for
displays that support 128b/132b but have DP_MSTM_CAP == 0.

> +		for(index = 0; index < ARRAY_SIZE(dp2dot0_fallback); index++) {
> +			if (link_rate == dp2dot0_fallback[index].link_rate &&
> +				lane_count == dp2dot0_fallback[index].lane_count) {
> +				for(index += 1; index < ARRAY_SIZE(dp2dot0_fallback); index++) {

I honestly do not understand the double looping here, and how index is
managed.

> +					if (intel_dp_link_rate_supported(intel_dp,
> +							dp2dot0_fallback[index].link_rate)) {
> +						intel_dp_set_link_params(intel_dp,
> +								      dp2dot0_fallback[index].link_rate,
> +								      dp2dot0_fallback[index].lane_count);

intel_dp_set_link_params() is supposed to be called in the DP encoder
(pre-)enable paths to set the link rates. If you do it here, the
subsequent enable will just overwrite whatever you did here.

The mechanism in this function should be to to adjust
intel_dp->max_link_rate and intel_dp->max_link_lane_count, and then the
caller will send an uevent to have the userspace do everything again,
but with reduced max values.

This is all very convoluted. And I admit the existing code is also
complex, but this makes it *much* harder to understand.

BR,
Jani.

> +						drm_dbg_kms(&i915->drm,
> +							    "Retrying Link training with link rate %d and lane count %d\n",
> +							    dp2dot0_fallback[index].link_rate,
> +							    dp2dot0_fallback[index].lane_count);
> +						return 0;
> +					}
> +				}
> +			}
> +		}
> +		/* Report failure and fail link training */
> +		drm_err(&i915->drm, "Link Training Unsuccessful\n");
> +		return -1;
> +	}
> +
>  	index = intel_dp_rate_index(intel_dp->common_rates,
>  				    intel_dp->num_common_rates,
>  				    link_rate);
> @@ -716,7 +789,6 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
>  		drm_err(&i915->drm, "Link Training Unsuccessful\n");
>  		return -1;
>  	}
> -
>  	return 0;
>  }

-- 
Jani Nikula, Intel



[Index of Archives]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux