diff mbox series

[RFC,1/6] drm/dp: get/set phy compliance pattern.

Message ID 20191003150653.15881-2-animesh.manna@intel.com (mailing list archive)
State New, archived
Headers show
Series DP Phy compliace auto test. | expand

Commit Message

Animesh Manna Oct. 3, 2019, 3:06 p.m. UTC
During phy complaince auto test mode source need to read
requested test pattern from sink through DPCD. After processing
the request source need to set the pattern. So set/get method
added in drm layer as it is DP protocol.

Signed-off-by: Animesh Manna <animesh.manna@intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 77 +++++++++++++++++++++++++++++++++
 include/drm/drm_dp_helper.h     | 28 ++++++++++++
 2 files changed, 105 insertions(+)

Comments

Navare, Manasi Oct. 21, 2019, 11:27 p.m. UTC | #1
On Thu, Oct 03, 2019 at 08:36:48PM +0530, Animesh Manna wrote:
> During phy complaince auto test mode source need to read
> requested test pattern from sink through DPCD. After processing
> the request source need to set the pattern. So set/get method
> added in drm layer as it is DP protocol.
> 
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 77 +++++++++++++++++++++++++++++++++
>  include/drm/drm_dp_helper.h     | 28 ++++++++++++
>  2 files changed, 105 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> index f373798d82f6..3cb7170e55f4 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -1484,3 +1484,80 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
>  	return num_bpc;
>  }
>  EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
> +
> +/**
> + * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
> + * @aux: DisplayPort AUX channel
> + * @data: DP phy compliance test parameters.
> + *
> + * Returns 0 on success or a negative error code on failure.
> + */
> +int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux,
> +				struct drm_dp_phy_test_params *data)
> +{
> +	int err;
> +
> +	err = drm_dp_link_probe(aux, &data->link);
> +	if (err < 0)
> +		return err;
> +
> +	err = drm_dp_dpcd_read(aux, DP_TEST_PHY_PATTERN, &data->phy_pattern, 1);

Just use drm_dp_dpcd_readb

> +	if (err < 0)
> +		return err;
> +
> +	switch (data->phy_pattern) {
> +	case DP_TEST_PHY_PATTERN_80BIT_CUSTOM:
> +		err = drm_dp_dpcd_read(aux, DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
> +				       &data->custom80, 10);
> +		if (err < 0)
> +			return err;
> +
> +		break;
> +	case DP_TEST_PHY_PATTERN_CP2520:
> +		err = drm_dp_dpcd_read(aux, DP_TEST_HBR2_SCRAMBLER_RESET,
> +				       &data->hbr2_reset, 2);
> +		if (err < 0)
> +			return err;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_dp_get_phy_test_pattern);
> +
> +/**
> + * drm_dp_set_phy_test_pattern() - set the pattern to the sink.
> + * @aux: DisplayPort AUX channel
> + * @data: DP phy compliance test parameters.
> + *
> + * Returns 0 on success or a negative error code on failure.
> + */
> +int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux,
> +				struct drm_dp_phy_test_params *data)
> +{
> +	int err, i;
> +	u8 test_pattern;
> +
> +	err = drm_dp_link_configure(aux, &data->link);
> +	if (err < 0)
> +		return err;
> +
> +	test_pattern = data->phy_pattern;
> +	if (data->link.revision < 0x12) {
> +		test_pattern = (test_pattern << 2) &
> +			       DP_LINK_QUAL_PATTERN_11_MASK;
> +		err = drm_dp_dpcd_write(aux, DP_TRAINING_PATTERN_SET,
> +					&test_pattern, 1);

Same, just use drm_dp_dpcd_writeb

> +		if (err < 0)
> +			return err;
> +	} else {
> +		for (i = 0; i < data->link.num_lanes; i++) {
> +			err = drm_dp_dpcd_write(aux, DP_LINK_QUAL_LANE0_SET + i,
> +						&test_pattern, 1);
> +			if (err < 0)
> +				return err;
> +		}
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_dp_set_phy_test_pattern);
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index ed1a985745ba..77dcf5879beb 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -691,6 +691,14 @@
>  # define DP_TEST_COUNT_MASK		    0xf
>  
>  #define DP_TEST_PHY_PATTERN                 0x248

This should be consistent with spec name DP_PHY_TEST_PATTERN

And since the bits below are part of the 2:0 PATTERN_SEL, I would prefer
having DP_PHY_TEST_PATTERN_SEL_MASK 0x7

> +# define DP_TEST_PHY_PATTERN_NONE           0
                                               ^ 0x0
> +# define DP_TEST_PHY_PATTERN_D10_2          1
                                               ^ 0x1 (to be consistent with other bit defs in .h file)

Manasi

> +# define DP_TEST_PHY_PATTERN_ERROR_COUNT    2
> +# define DP_TEST_PHY_PATTERN_PRBS7          3
> +# define DP_TEST_PHY_PATTERN_80BIT_CUSTOM   4
> +# define DP_TEST_PHY_PATTERN_CP2520         5
> +
> +#define DP_TEST_HBR2_SCRAMBLER_RESET        0x24A
>  #define DP_TEST_80BIT_CUSTOM_PATTERN_7_0    0x250
>  #define	DP_TEST_80BIT_CUSTOM_PATTERN_15_8   0x251
>  #define	DP_TEST_80BIT_CUSTOM_PATTERN_23_16  0x252
> @@ -1523,4 +1531,24 @@ static inline void drm_dp_cec_unset_edid(struct drm_dp_aux *aux)
>  
>  #endif
>  
> +/**
> + * struct drm_dp_phy_test_params - DP Phy Compliance parameters
> + * @link: Link information.
> + * @phy_pattern: DP Phy test pattern from DPCD 0x248 (sink)
> + * @hb2_reset: DP HBR2_COMPLIANCE_SCRAMBLER_RESET from DCPD
> + *            0x24A and 0x24B (sink)
> + * @custom80: DP Test_80BIT_CUSTOM_PATTERN from DPCDs 0x250
> + *               through 0x259.
> + */
> +struct drm_dp_phy_test_params {
> +	struct drm_dp_link link;
> +	u8 phy_pattern;
> +	u8 hbr2_reset[2];
> +	u8 custom80[10];
> +};
> +
> +int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux,
> +				struct drm_dp_phy_test_params *data);
> +int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux,
> +				struct drm_dp_phy_test_params *data);
>  #endif /* _DRM_DP_HELPER_H_ */
> -- 
> 2.22.0
>
Animesh Manna Oct. 22, 2019, 1:29 p.m. UTC | #2
On 10/22/2019 4:57 AM, Manasi Navare wrote:
> On Thu, Oct 03, 2019 at 08:36:48PM +0530, Animesh Manna wrote:
>> During phy complaince auto test mode source need to read
>> requested test pattern from sink through DPCD. After processing
>> the request source need to set the pattern. So set/get method
>> added in drm layer as it is DP protocol.
>>
>> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
>> ---
>>   drivers/gpu/drm/drm_dp_helper.c | 77 +++++++++++++++++++++++++++++++++
>>   include/drm/drm_dp_helper.h     | 28 ++++++++++++
>>   2 files changed, 105 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
>> index f373798d82f6..3cb7170e55f4 100644
>> --- a/drivers/gpu/drm/drm_dp_helper.c
>> +++ b/drivers/gpu/drm/drm_dp_helper.c
>> @@ -1484,3 +1484,80 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
>>   	return num_bpc;
>>   }
>>   EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
>> +
>> +/**
>> + * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
>> + * @aux: DisplayPort AUX channel
>> + * @data: DP phy compliance test parameters.
>> + *
>> + * Returns 0 on success or a negative error code on failure.
>> + */
>> +int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux,
>> +				struct drm_dp_phy_test_params *data)
>> +{
>> +	int err;
>> +
>> +	err = drm_dp_link_probe(aux, &data->link);
>> +	if (err < 0)
>> +		return err;
>> +
>> +	err = drm_dp_dpcd_read(aux, DP_TEST_PHY_PATTERN, &data->phy_pattern, 1);
> Just use drm_dp_dpcd_readb

Thanks Manasi for code review.
Will add all suggested changes here.

Regards,
Animesh
>
>> +	if (err < 0)
>> +		return err;
>> +
>> +	switch (data->phy_pattern) {
>> +	case DP_TEST_PHY_PATTERN_80BIT_CUSTOM:
>> +		err = drm_dp_dpcd_read(aux, DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
>> +				       &data->custom80, 10);
>> +		if (err < 0)
>> +			return err;
>> +
>> +		break;
>> +	case DP_TEST_PHY_PATTERN_CP2520:
>> +		err = drm_dp_dpcd_read(aux, DP_TEST_HBR2_SCRAMBLER_RESET,
>> +				       &data->hbr2_reset, 2);
>> +		if (err < 0)
>> +			return err;
>> +	}
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL(drm_dp_get_phy_test_pattern);
>> +
>> +/**
>> + * drm_dp_set_phy_test_pattern() - set the pattern to the sink.
>> + * @aux: DisplayPort AUX channel
>> + * @data: DP phy compliance test parameters.
>> + *
>> + * Returns 0 on success or a negative error code on failure.
>> + */
>> +int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux,
>> +				struct drm_dp_phy_test_params *data)
>> +{
>> +	int err, i;
>> +	u8 test_pattern;
>> +
>> +	err = drm_dp_link_configure(aux, &data->link);
>> +	if (err < 0)
>> +		return err;
>> +
>> +	test_pattern = data->phy_pattern;
>> +	if (data->link.revision < 0x12) {
>> +		test_pattern = (test_pattern << 2) &
>> +			       DP_LINK_QUAL_PATTERN_11_MASK;
>> +		err = drm_dp_dpcd_write(aux, DP_TRAINING_PATTERN_SET,
>> +					&test_pattern, 1);
> Same, just use drm_dp_dpcd_writeb
>
>> +		if (err < 0)
>> +			return err;
>> +	} else {
>> +		for (i = 0; i < data->link.num_lanes; i++) {
>> +			err = drm_dp_dpcd_write(aux, DP_LINK_QUAL_LANE0_SET + i,
>> +						&test_pattern, 1);
>> +			if (err < 0)
>> +				return err;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL(drm_dp_set_phy_test_pattern);
>> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
>> index ed1a985745ba..77dcf5879beb 100644
>> --- a/include/drm/drm_dp_helper.h
>> +++ b/include/drm/drm_dp_helper.h
>> @@ -691,6 +691,14 @@
>>   # define DP_TEST_COUNT_MASK		    0xf
>>   
>>   #define DP_TEST_PHY_PATTERN                 0x248
> This should be consistent with spec name DP_PHY_TEST_PATTERN
>
> And since the bits below are part of the 2:0 PATTERN_SEL, I would prefer
> having DP_PHY_TEST_PATTERN_SEL_MASK 0x7
>
>> +# define DP_TEST_PHY_PATTERN_NONE           0
>                                                 ^ 0x0
>> +# define DP_TEST_PHY_PATTERN_D10_2          1
>                                                 ^ 0x1 (to be consistent with other bit defs in .h file)
>
> Manasi
>
>> +# define DP_TEST_PHY_PATTERN_ERROR_COUNT    2
>> +# define DP_TEST_PHY_PATTERN_PRBS7          3
>> +# define DP_TEST_PHY_PATTERN_80BIT_CUSTOM   4
>> +# define DP_TEST_PHY_PATTERN_CP2520         5
>> +
>> +#define DP_TEST_HBR2_SCRAMBLER_RESET        0x24A
>>   #define DP_TEST_80BIT_CUSTOM_PATTERN_7_0    0x250
>>   #define	DP_TEST_80BIT_CUSTOM_PATTERN_15_8   0x251
>>   #define	DP_TEST_80BIT_CUSTOM_PATTERN_23_16  0x252
>> @@ -1523,4 +1531,24 @@ static inline void drm_dp_cec_unset_edid(struct drm_dp_aux *aux)
>>   
>>   #endif
>>   
>> +/**
>> + * struct drm_dp_phy_test_params - DP Phy Compliance parameters
>> + * @link: Link information.
>> + * @phy_pattern: DP Phy test pattern from DPCD 0x248 (sink)
>> + * @hb2_reset: DP HBR2_COMPLIANCE_SCRAMBLER_RESET from DCPD
>> + *            0x24A and 0x24B (sink)
>> + * @custom80: DP Test_80BIT_CUSTOM_PATTERN from DPCDs 0x250
>> + *               through 0x259.
>> + */
>> +struct drm_dp_phy_test_params {
>> +	struct drm_dp_link link;
>> +	u8 phy_pattern;
>> +	u8 hbr2_reset[2];
>> +	u8 custom80[10];
>> +};
>> +
>> +int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux,
>> +				struct drm_dp_phy_test_params *data);
>> +int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux,
>> +				struct drm_dp_phy_test_params *data);
>>   #endif /* _DRM_DP_HELPER_H_ */
>> -- 
>> 2.22.0
>>
Navare, Manasi Nov. 5, 2019, 11:12 p.m. UTC | #3
On Thu, Oct 03, 2019 at 08:36:48PM +0530, Animesh Manna wrote:
> During phy complaince auto test mode source need to read
> requested test pattern from sink through DPCD. After processing
> the request source need to set the pattern. So set/get method
> added in drm layer as it is DP protocol.
> 
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 77 +++++++++++++++++++++++++++++++++
>  include/drm/drm_dp_helper.h     | 28 ++++++++++++
>  2 files changed, 105 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> index f373798d82f6..3cb7170e55f4 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -1484,3 +1484,80 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
>  	return num_bpc;
>  }
>  EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
> +
> +/**
> + * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
> + * @aux: DisplayPort AUX channel
> + * @data: DP phy compliance test parameters.
> + *
> + * Returns 0 on success or a negative error code on failure.
> + */
> +int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux,
> +				struct drm_dp_phy_test_params *data)
> +{
> +	int err;
> +
> +	err = drm_dp_link_probe(aux, &data->link);

Here this just reads the Sink capabilities and reads the max link rate and lane count
and stores that into the phy test link. But after talking to Clint here he pointed
out that for PHY compliance, you should be reading the TEST_LINK_RATE and TEST_LANE_COUNT
as the requested link config.

> +	if (err < 0)
> +		return err;
> +
> +	err = drm_dp_dpcd_read(aux, DP_TEST_PHY_PATTERN, &data->phy_pattern, 1);
> +	if (err < 0)
> +		return err;
> +
> +	switch (data->phy_pattern) {
> +	case DP_TEST_PHY_PATTERN_80BIT_CUSTOM:
> +		err = drm_dp_dpcd_read(aux, DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
> +				       &data->custom80, 10);
> +		if (err < 0)
> +			return err;
> +
> +		break;
> +	case DP_TEST_PHY_PATTERN_CP2520:
> +		err = drm_dp_dpcd_read(aux, DP_TEST_HBR2_SCRAMBLER_RESET,
> +				       &data->hbr2_reset, 2);
> +		if (err < 0)
> +			return err;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_dp_get_phy_test_pattern);
> +
> +/**
> + * drm_dp_set_phy_test_pattern() - set the pattern to the sink.
> + * @aux: DisplayPort AUX channel
> + * @data: DP phy compliance test parameters.
> + *
> + * Returns 0 on success or a negative error code on failure.
> + */
> +int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux,
> +				struct drm_dp_phy_test_params *data)
> +{
> +	int err, i;
> +	u8 test_pattern;
> +
> +	err = drm_dp_link_configure(aux, &data->link);

So here this function write sto the sink's DPCD registers to set the
link rate and lane count, however we havent set the display controller HW to that link rate
since we call this out of atomic modeset context.

Another reason why all this needs to happen in the context of atomic modeset

Manasi

> +	if (err < 0)
> +		return err;
> +
> +	test_pattern = data->phy_pattern;
> +	if (data->link.revision < 0x12) {
> +		test_pattern = (test_pattern << 2) &
> +			       DP_LINK_QUAL_PATTERN_11_MASK;
> +		err = drm_dp_dpcd_write(aux, DP_TRAINING_PATTERN_SET,
> +					&test_pattern, 1);
> +		if (err < 0)
> +			return err;
> +	} else {
> +		for (i = 0; i < data->link.num_lanes; i++) {
> +			err = drm_dp_dpcd_write(aux, DP_LINK_QUAL_LANE0_SET + i,
> +						&test_pattern, 1);
> +			if (err < 0)
> +				return err;
> +		}
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_dp_set_phy_test_pattern);
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index ed1a985745ba..77dcf5879beb 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -691,6 +691,14 @@
>  # define DP_TEST_COUNT_MASK		    0xf
>  
>  #define DP_TEST_PHY_PATTERN                 0x248
> +# define DP_TEST_PHY_PATTERN_NONE           0
> +# define DP_TEST_PHY_PATTERN_D10_2          1
> +# define DP_TEST_PHY_PATTERN_ERROR_COUNT    2
> +# define DP_TEST_PHY_PATTERN_PRBS7          3
> +# define DP_TEST_PHY_PATTERN_80BIT_CUSTOM   4
> +# define DP_TEST_PHY_PATTERN_CP2520         5
> +
> +#define DP_TEST_HBR2_SCRAMBLER_RESET        0x24A
>  #define DP_TEST_80BIT_CUSTOM_PATTERN_7_0    0x250
>  #define	DP_TEST_80BIT_CUSTOM_PATTERN_15_8   0x251
>  #define	DP_TEST_80BIT_CUSTOM_PATTERN_23_16  0x252
> @@ -1523,4 +1531,24 @@ static inline void drm_dp_cec_unset_edid(struct drm_dp_aux *aux)
>  
>  #endif
>  
> +/**
> + * struct drm_dp_phy_test_params - DP Phy Compliance parameters
> + * @link: Link information.
> + * @phy_pattern: DP Phy test pattern from DPCD 0x248 (sink)
> + * @hb2_reset: DP HBR2_COMPLIANCE_SCRAMBLER_RESET from DCPD
> + *            0x24A and 0x24B (sink)
> + * @custom80: DP Test_80BIT_CUSTOM_PATTERN from DPCDs 0x250
> + *               through 0x259.
> + */
> +struct drm_dp_phy_test_params {
> +	struct drm_dp_link link;
> +	u8 phy_pattern;
> +	u8 hbr2_reset[2];
> +	u8 custom80[10];
> +};
> +
> +int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux,
> +				struct drm_dp_phy_test_params *data);
> +int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux,
> +				struct drm_dp_phy_test_params *data);
>  #endif /* _DRM_DP_HELPER_H_ */
> -- 
> 2.22.0
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index f373798d82f6..3cb7170e55f4 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -1484,3 +1484,80 @@  int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
 	return num_bpc;
 }
 EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
+
+/**
+ * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
+ * @aux: DisplayPort AUX channel
+ * @data: DP phy compliance test parameters.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux,
+				struct drm_dp_phy_test_params *data)
+{
+	int err;
+
+	err = drm_dp_link_probe(aux, &data->link);
+	if (err < 0)
+		return err;
+
+	err = drm_dp_dpcd_read(aux, DP_TEST_PHY_PATTERN, &data->phy_pattern, 1);
+	if (err < 0)
+		return err;
+
+	switch (data->phy_pattern) {
+	case DP_TEST_PHY_PATTERN_80BIT_CUSTOM:
+		err = drm_dp_dpcd_read(aux, DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
+				       &data->custom80, 10);
+		if (err < 0)
+			return err;
+
+		break;
+	case DP_TEST_PHY_PATTERN_CP2520:
+		err = drm_dp_dpcd_read(aux, DP_TEST_HBR2_SCRAMBLER_RESET,
+				       &data->hbr2_reset, 2);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_get_phy_test_pattern);
+
+/**
+ * drm_dp_set_phy_test_pattern() - set the pattern to the sink.
+ * @aux: DisplayPort AUX channel
+ * @data: DP phy compliance test parameters.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux,
+				struct drm_dp_phy_test_params *data)
+{
+	int err, i;
+	u8 test_pattern;
+
+	err = drm_dp_link_configure(aux, &data->link);
+	if (err < 0)
+		return err;
+
+	test_pattern = data->phy_pattern;
+	if (data->link.revision < 0x12) {
+		test_pattern = (test_pattern << 2) &
+			       DP_LINK_QUAL_PATTERN_11_MASK;
+		err = drm_dp_dpcd_write(aux, DP_TRAINING_PATTERN_SET,
+					&test_pattern, 1);
+		if (err < 0)
+			return err;
+	} else {
+		for (i = 0; i < data->link.num_lanes; i++) {
+			err = drm_dp_dpcd_write(aux, DP_LINK_QUAL_LANE0_SET + i,
+						&test_pattern, 1);
+			if (err < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_set_phy_test_pattern);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index ed1a985745ba..77dcf5879beb 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -691,6 +691,14 @@ 
 # define DP_TEST_COUNT_MASK		    0xf
 
 #define DP_TEST_PHY_PATTERN                 0x248
+# define DP_TEST_PHY_PATTERN_NONE           0
+# define DP_TEST_PHY_PATTERN_D10_2          1
+# define DP_TEST_PHY_PATTERN_ERROR_COUNT    2
+# define DP_TEST_PHY_PATTERN_PRBS7          3
+# define DP_TEST_PHY_PATTERN_80BIT_CUSTOM   4
+# define DP_TEST_PHY_PATTERN_CP2520         5
+
+#define DP_TEST_HBR2_SCRAMBLER_RESET        0x24A
 #define DP_TEST_80BIT_CUSTOM_PATTERN_7_0    0x250
 #define	DP_TEST_80BIT_CUSTOM_PATTERN_15_8   0x251
 #define	DP_TEST_80BIT_CUSTOM_PATTERN_23_16  0x252
@@ -1523,4 +1531,24 @@  static inline void drm_dp_cec_unset_edid(struct drm_dp_aux *aux)
 
 #endif
 
+/**
+ * struct drm_dp_phy_test_params - DP Phy Compliance parameters
+ * @link: Link information.
+ * @phy_pattern: DP Phy test pattern from DPCD 0x248 (sink)
+ * @hb2_reset: DP HBR2_COMPLIANCE_SCRAMBLER_RESET from DCPD
+ *            0x24A and 0x24B (sink)
+ * @custom80: DP Test_80BIT_CUSTOM_PATTERN from DPCDs 0x250
+ *               through 0x259.
+ */
+struct drm_dp_phy_test_params {
+	struct drm_dp_link link;
+	u8 phy_pattern;
+	u8 hbr2_reset[2];
+	u8 custom80[10];
+};
+
+int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux,
+				struct drm_dp_phy_test_params *data);
+int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux,
+				struct drm_dp_phy_test_params *data);
 #endif /* _DRM_DP_HELPER_H_ */