diff mbox series

[v4] drm: Add support for DP 1.4 Compliance edid corruption test 4.2.2.6

Message ID 20191105163740.3093-1-Jerry.Zuo@amd.com (mailing list archive)
State New, archived
Headers show
Series [v4] drm: Add support for DP 1.4 Compliance edid corruption test 4.2.2.6 | expand

Commit Message

Fangzhi Zuo Nov. 5, 2019, 4:37 p.m. UTC
DP 1.4 edid corruption test requires source DUT to write calculated
CRC, not the corrupted CRC from reference sink.

Return the calculated CRC back, and initiate the required sequence.

-v2: Have separate routine for returning real CRC

-v3: Rewrite checksum computation routine to avoid duplicated code.
     Rename to avoid confusion

-v4: Fix a minor typo.

Signed-off-by: Jerry (Fangzhi) Zuo <Jerry.Zuo@amd.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 36 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_edid.c      | 18 +++++++++++++++---
 include/drm/drm_connector.h     |  7 +++++++
 include/drm/drm_dp_helper.h     |  3 +++
 4 files changed, 61 insertions(+), 3 deletions(-)

Comments

Fangzhi Zuo Nov. 25, 2019, 9:36 p.m. UTC | #1
Please kindly give a review on my latest revision. Thanks a lot.

Regards,
Jerry

-----Original Message-----
From: Jerry (Fangzhi) Zuo <Jerry.Zuo@amd.com> 
Sent: November 5, 2019 11:38 AM
To: dri-devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org
Cc: lyude@redhat.com; manasi.d.navare@intel.com; Wentland, Harry <Harry.Wentland@amd.com>; Zuo, Jerry <Jerry.Zuo@amd.com>
Subject: [PATCH v4] drm: Add support for DP 1.4 Compliance edid corruption test 4.2.2.6

DP 1.4 edid corruption test requires source DUT to write calculated CRC, not the corrupted CRC from reference sink.

Return the calculated CRC back, and initiate the required sequence.

-v2: Have separate routine for returning real CRC

-v3: Rewrite checksum computation routine to avoid duplicated code.
     Rename to avoid confusion

-v4: Fix a minor typo.

Signed-off-by: Jerry (Fangzhi) Zuo <Jerry.Zuo@amd.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 36 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_edid.c      | 18 +++++++++++++++---
 include/drm/drm_connector.h     |  7 +++++++
 include/drm/drm_dp_helper.h     |  3 +++
 4 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index ffc68d305afe..22a0e966ea9f 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -336,6 +336,42 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,  }  EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
 
+/**
+  * drm_dp_send_real_edid_checksum() - send back real edid checksum 
+value
+  * @aux: DisplayPort AUX channel
+  * @real_edid_checksum: real edid checksum for the last block
+  *
+  * Returns true on success
+  */
+bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
+                                u8 real_edid_checksum) {
+        u8 link_edid_read = 0, auto_test_req = 0;
+        u8 test_resp = 0;
+
+        drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, &auto_test_req, 1);
+        auto_test_req &= DP_AUTOMATED_TEST_REQUEST;
+
+        drm_dp_dpcd_read(aux, DP_TEST_REQUEST, &link_edid_read, 1);
+        link_edid_read &= DP_TEST_LINK_EDID_READ;
+
+        if (!auto_test_req || !link_edid_read) {
+                DRM_DEBUG_KMS("Source DUT does not support TEST_EDID_READ\n");
+                return false;
+        }
+
+        drm_dp_dpcd_write(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, 
+ &auto_test_req, 1);
+
+        /* send back checksum for the last edid extension block data */
+        drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM, 
+ &real_edid_checksum, 1);
+
+        test_resp |= DP_TEST_EDID_CHECKSUM_WRITE;
+        drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, &test_resp, 1);
+
+        return true;
+}
+EXPORT_SYMBOL(drm_dp_send_real_edid_checksum);
+
 /**
  * drm_dp_link_probe() - probe a DisplayPort link for capabilities
  * @aux: DisplayPort AUX channel
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 82a4ceed3fcf..ff64e5f1feb6 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1348,10 +1348,19 @@ static int drm_edid_block_checksum(const u8 *raw_edid)  {
 	int i;
 	u8 csum = 0;
-	for (i = 0; i < EDID_LENGTH; i++)
+
+	for (i = 0; i < EDID_LENGTH - 1; i++)
 		csum += raw_edid[i];
 
-	return csum;
+	return (0x100 - csum);
+}
+
+static bool drm_edid_block_checksum_diff(const u8 *raw_edid, u8 
+real_checksum) {
+	if (raw_edid[EDID_LENGTH - 1] != real_checksum)
+		return true;
+	else
+		return false;
 }
 
 static bool drm_edid_is_zero(const u8 *in_edid, int length) @@ -1409,7 +1418,7 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid,
 	}
 
 	csum = drm_edid_block_checksum(raw_edid);
-	if (csum) {
+	if (drm_edid_block_checksum_diff(raw_edid, csum)) {
 		if (edid_corrupt)
 			*edid_corrupt = true;
 
@@ -1572,6 +1581,9 @@ static void connector_bad_edid(struct drm_connector *connector,
 			       prefix, DUMP_PREFIX_NONE, 16, 1,
 			       block, EDID_LENGTH, false);
 	}
+
+	/* Calculate real checksum for the last edid extension block data */
+	connector->real_edid_checksum = drm_edid_block_checksum(edid + 
+edid[0x7e] * EDID_LENGTH);
 }
 
 /* Get override or firmware EDID */
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 681cb590f952..eb0d8c7b35fd 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1345,6 +1345,13 @@ struct drm_connector {
 	 * rev1.1 4.2.2.6
 	 */
 	bool edid_corrupt;
+	/**
+         * @real_edid_checksum: real edid checksum value for corrupted edid block.
+         * Required in Displayport 1.4 compliance testing
+         * rev1.1 4.2.2.6
+         */
+        uint8_t real_edid_checksum;
+
 
 	/** @debugfs_entry: debugfs directory for this connector */
 	struct dentry *debugfs_entry;
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 5a795075d5da..84709d7810f8 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1383,6 +1383,9 @@ static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux,  int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
 				 u8 status[DP_LINK_STATUS_SIZE]);
 
+bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
+				    u8 real_edid_checksum);
+
 /*
  * DisplayPort link
  */
--
2.14.1
Harry Wentland Nov. 26, 2019, 6:39 p.m. UTC | #2
On 2019-11-25 4:36 p.m., Zuo, Jerry wrote:
> Please kindly give a review on my latest revision. Thanks a lot.
> 

Both patches are
Reviewed-by: Harry Wentland <harry.wentland@amd.com>

Harry

> Regards,
> Jerry
> 
> -----Original Message-----
> From: Jerry (Fangzhi) Zuo <Jerry.Zuo@amd.com> 
> Sent: November 5, 2019 11:38 AM
> To: dri-devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org
> Cc: lyude@redhat.com; manasi.d.navare@intel.com; Wentland, Harry <Harry.Wentland@amd.com>; Zuo, Jerry <Jerry.Zuo@amd.com>
> Subject: [PATCH v4] drm: Add support for DP 1.4 Compliance edid corruption test 4.2.2.6
> 
> DP 1.4 edid corruption test requires source DUT to write calculated CRC, not the corrupted CRC from reference sink.
> 
> Return the calculated CRC back, and initiate the required sequence.
> 
> -v2: Have separate routine for returning real CRC
> 
> -v3: Rewrite checksum computation routine to avoid duplicated code.
>      Rename to avoid confusion
> 
> -v4: Fix a minor typo.
> 
> Signed-off-by: Jerry (Fangzhi) Zuo <Jerry.Zuo@amd.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 36 ++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/drm_edid.c      | 18 +++++++++++++++---
>  include/drm/drm_connector.h     |  7 +++++++
>  include/drm/drm_dp_helper.h     |  3 +++
>  4 files changed, 61 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index ffc68d305afe..22a0e966ea9f 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -336,6 +336,42 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,  }  EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
>  
> +/**
> +  * drm_dp_send_real_edid_checksum() - send back real edid checksum 
> +value
> +  * @aux: DisplayPort AUX channel
> +  * @real_edid_checksum: real edid checksum for the last block
> +  *
> +  * Returns true on success
> +  */
> +bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
> +                                u8 real_edid_checksum) {
> +        u8 link_edid_read = 0, auto_test_req = 0;
> +        u8 test_resp = 0;
> +
> +        drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, &auto_test_req, 1);
> +        auto_test_req &= DP_AUTOMATED_TEST_REQUEST;
> +
> +        drm_dp_dpcd_read(aux, DP_TEST_REQUEST, &link_edid_read, 1);
> +        link_edid_read &= DP_TEST_LINK_EDID_READ;
> +
> +        if (!auto_test_req || !link_edid_read) {
> +                DRM_DEBUG_KMS("Source DUT does not support TEST_EDID_READ\n");
> +                return false;
> +        }
> +
> +        drm_dp_dpcd_write(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, 
> + &auto_test_req, 1);
> +
> +        /* send back checksum for the last edid extension block data */
> +        drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM, 
> + &real_edid_checksum, 1);
> +
> +        test_resp |= DP_TEST_EDID_CHECKSUM_WRITE;
> +        drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, &test_resp, 1);
> +
> +        return true;
> +}
> +EXPORT_SYMBOL(drm_dp_send_real_edid_checksum);
> +
>  /**
>   * drm_dp_link_probe() - probe a DisplayPort link for capabilities
>   * @aux: DisplayPort AUX channel
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 82a4ceed3fcf..ff64e5f1feb6 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -1348,10 +1348,19 @@ static int drm_edid_block_checksum(const u8 *raw_edid)  {
>  	int i;
>  	u8 csum = 0;
> -	for (i = 0; i < EDID_LENGTH; i++)
> +
> +	for (i = 0; i < EDID_LENGTH - 1; i++)
>  		csum += raw_edid[i];
>  
> -	return csum;
> +	return (0x100 - csum);
> +}
> +
> +static bool drm_edid_block_checksum_diff(const u8 *raw_edid, u8 
> +real_checksum) {
> +	if (raw_edid[EDID_LENGTH - 1] != real_checksum)
> +		return true;
> +	else
> +		return false;
>  }
>  
>  static bool drm_edid_is_zero(const u8 *in_edid, int length) @@ -1409,7 +1418,7 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid,
>  	}
>  
>  	csum = drm_edid_block_checksum(raw_edid);
> -	if (csum) {
> +	if (drm_edid_block_checksum_diff(raw_edid, csum)) {
>  		if (edid_corrupt)
>  			*edid_corrupt = true;
>  
> @@ -1572,6 +1581,9 @@ static void connector_bad_edid(struct drm_connector *connector,
>  			       prefix, DUMP_PREFIX_NONE, 16, 1,
>  			       block, EDID_LENGTH, false);
>  	}
> +
> +	/* Calculate real checksum for the last edid extension block data */
> +	connector->real_edid_checksum = drm_edid_block_checksum(edid + 
> +edid[0x7e] * EDID_LENGTH);
>  }
>  
>  /* Get override or firmware EDID */
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 681cb590f952..eb0d8c7b35fd 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -1345,6 +1345,13 @@ struct drm_connector {
>  	 * rev1.1 4.2.2.6
>  	 */
>  	bool edid_corrupt;
> +	/**
> +         * @real_edid_checksum: real edid checksum value for corrupted edid block.
> +         * Required in Displayport 1.4 compliance testing
> +         * rev1.1 4.2.2.6
> +         */
> +        uint8_t real_edid_checksum;
> +
>  
>  	/** @debugfs_entry: debugfs directory for this connector */
>  	struct dentry *debugfs_entry;
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 5a795075d5da..84709d7810f8 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1383,6 +1383,9 @@ static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux,  int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
>  				 u8 status[DP_LINK_STATUS_SIZE]);
>  
> +bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
> +				    u8 real_edid_checksum);
> +
>  /*
>   * DisplayPort link
>   */
> --
> 2.14.1
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index ffc68d305afe..22a0e966ea9f 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -336,6 +336,42 @@  int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
 }
 EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
 
+/**
+  * drm_dp_send_real_edid_checksum() - send back real edid checksum value
+  * @aux: DisplayPort AUX channel
+  * @real_edid_checksum: real edid checksum for the last block
+  *
+  * Returns true on success
+  */
+bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
+                                u8 real_edid_checksum)
+{
+        u8 link_edid_read = 0, auto_test_req = 0;
+        u8 test_resp = 0;
+
+        drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, &auto_test_req, 1);
+        auto_test_req &= DP_AUTOMATED_TEST_REQUEST;
+
+        drm_dp_dpcd_read(aux, DP_TEST_REQUEST, &link_edid_read, 1);
+        link_edid_read &= DP_TEST_LINK_EDID_READ;
+
+        if (!auto_test_req || !link_edid_read) {
+                DRM_DEBUG_KMS("Source DUT does not support TEST_EDID_READ\n");
+                return false;
+        }
+
+        drm_dp_dpcd_write(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, &auto_test_req, 1);
+
+        /* send back checksum for the last edid extension block data */
+        drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM, &real_edid_checksum, 1);
+
+        test_resp |= DP_TEST_EDID_CHECKSUM_WRITE;
+        drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, &test_resp, 1);
+
+        return true;
+}
+EXPORT_SYMBOL(drm_dp_send_real_edid_checksum);
+
 /**
  * drm_dp_link_probe() - probe a DisplayPort link for capabilities
  * @aux: DisplayPort AUX channel
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 82a4ceed3fcf..ff64e5f1feb6 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1348,10 +1348,19 @@  static int drm_edid_block_checksum(const u8 *raw_edid)
 {
 	int i;
 	u8 csum = 0;
-	for (i = 0; i < EDID_LENGTH; i++)
+
+	for (i = 0; i < EDID_LENGTH - 1; i++)
 		csum += raw_edid[i];
 
-	return csum;
+	return (0x100 - csum);
+}
+
+static bool drm_edid_block_checksum_diff(const u8 *raw_edid, u8 real_checksum)
+{
+	if (raw_edid[EDID_LENGTH - 1] != real_checksum)
+		return true;
+	else
+		return false;
 }
 
 static bool drm_edid_is_zero(const u8 *in_edid, int length)
@@ -1409,7 +1418,7 @@  bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid,
 	}
 
 	csum = drm_edid_block_checksum(raw_edid);
-	if (csum) {
+	if (drm_edid_block_checksum_diff(raw_edid, csum)) {
 		if (edid_corrupt)
 			*edid_corrupt = true;
 
@@ -1572,6 +1581,9 @@  static void connector_bad_edid(struct drm_connector *connector,
 			       prefix, DUMP_PREFIX_NONE, 16, 1,
 			       block, EDID_LENGTH, false);
 	}
+
+	/* Calculate real checksum for the last edid extension block data */
+	connector->real_edid_checksum = drm_edid_block_checksum(edid + edid[0x7e] * EDID_LENGTH);
 }
 
 /* Get override or firmware EDID */
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 681cb590f952..eb0d8c7b35fd 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1345,6 +1345,13 @@  struct drm_connector {
 	 * rev1.1 4.2.2.6
 	 */
 	bool edid_corrupt;
+	/**
+         * @real_edid_checksum: real edid checksum value for corrupted edid block.
+         * Required in Displayport 1.4 compliance testing
+         * rev1.1 4.2.2.6
+         */
+        uint8_t real_edid_checksum;
+
 
 	/** @debugfs_entry: debugfs directory for this connector */
 	struct dentry *debugfs_entry;
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 5a795075d5da..84709d7810f8 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1383,6 +1383,9 @@  static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux,
 int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
 				 u8 status[DP_LINK_STATUS_SIZE]);
 
+bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
+				    u8 real_edid_checksum);
+
 /*
  * DisplayPort link
  */