[Intel-gfx] [PATCH V7] drm: Add support for DP 1.4 Compliance edid corruption test

2020-02-12 Thread Jerry (Fangzhi) Zuo
Unlike DP 1.2 edid corruption test, DP 1.4 requires to calculate
real CRC value of the last edid data block, and write it back.
Current edid CRC calculates routine adds the last CRC byte,
and check if non-zero.

This behavior is not accurate; actually, we need to return
the actual CRC value when corruption is detected.
This commit changes this issue by returning the calculated CRC,
and initiate the required sequence.

Change since v7
- Fix for CI.CHECKPATCH

Change since v6
- Add return check

Change since v5
- Obtain real CRC value before dumping bad edid

Change since v4
- Fix for CI.CHECKPATCH

Change since v3
- Fix a minor typo.

Change since v2
- Rewrite checksum computation routine to avoid duplicated code.
- Rename to avoid confusion.

Change since v1
- Have separate routine for returning real CRC.

Signed-off-by: Jerry (Fangzhi) Zuo 
Reviewed-by: Harry Wentland 
Reviewed-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/drm_dp_helper.c | 59 +
 drivers/gpu/drm/drm_edid.c  | 24 +++---
 include/drm/drm_connector.h |  6 
 include/drm/drm_dp_helper.h |  3 ++
 4 files changed, 88 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index f629fc5494a4..43e9f1968af4 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -351,6 +351,65 @@ 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, test_resp = 0;
+
+   if (drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR,
+_test_req, 1) < 1) {
+   DRM_ERROR("DPCD failed read at register 0x%x\n",
+ DP_DEVICE_SERVICE_IRQ_VECTOR);
+   return false;
+   }
+   auto_test_req &= DP_AUTOMATED_TEST_REQUEST;
+
+   if (drm_dp_dpcd_read(aux, DP_TEST_REQUEST, _edid_read, 1) < 1) {
+   DRM_ERROR("DPCD failed read at register 0x%x\n",
+ DP_TEST_REQUEST);
+   return false;
+   }
+   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;
+   }
+
+   if (drm_dp_dpcd_write(aux, DP_DEVICE_SERVICE_IRQ_VECTOR,
+ _test_req, 1) < 1) {
+   DRM_ERROR("DPCD failed write at register 0x%x\n",
+ DP_DEVICE_SERVICE_IRQ_VECTOR);
+   return false;
+   }
+
+   /* send back checksum for the last edid extension block data */
+   if (drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM,
+ _edid_checksum, 1) < 1) {
+   DRM_ERROR("DPCD failed write at register 0x%x\n",
+ DP_TEST_EDID_CHECKSUM);
+   return false;
+   }
+
+   test_resp |= DP_TEST_EDID_CHECKSUM_WRITE;
+   if (drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, _resp, 1) < 1) {
+   DRM_ERROR("DPCD failed write at register 0x%x\n",
+ DP_TEST_RESPONSE);
+   return false;
+   }
+
+   return true;
+}
+EXPORT_SYMBOL(drm_dp_send_real_edid_checksum);
+
 /**
  * drm_dp_downstream_max_clock() - extract branch device max
  * pixel rate for legacy VGA
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 99769d6c9f84..1fcec5f4c3ec 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1590,11 +1590,22 @@ static int validate_displayid(u8 *displayid, int 
length, int idx);
 static int drm_edid_block_checksum(const u8 *raw_edid)
 {
int i;
-   u8 csum = 0;
-   for (i = 0; i < EDID_LENGTH; i++)
+   u8 csum = 0, crc = 0;
+
+   for (i = 0; i < EDID_LENGTH - 1; i++)
csum += raw_edid[i];
 
-   return csum;
+   crc = 0x100 - csum;
+
+   return crc;
+}
+
+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)
@@ -1652,7 +1663,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)) {

[Intel-gfx] [PATCH V6] drm: Add support for DP 1.4 Compliance edid corruption test

2020-02-06 Thread Jerry (Fangzhi) Zuo
Unlike DP 1.2 edid corruption test, DP 1.4 requires to calculate
real CRC value of the last edid data block, and write it back.
Current edid CRC calculates routine adds the last CRC byte,
and check if non-zero.

This behavior is not accurate; actually, we need to return
the actual CRC value when corruption is detected.
This commit changes this issue by returning the calculated CRC,
and initiate the required sequence.

Change since v6
- Add return check

Change since v5
- Obtain real CRC value before dumping bad edid

Change since v4
- Fix for CI.CHECKPATCH

Change since v3
- Fix a minor typo.

Change since v2
- Rewrite checksum computation routine to avoid duplicated code.
- Rename to avoid confusion.

Change since v1
- Have separate routine for returning real CRC.

Signed-off-by: Jerry (Fangzhi) Zuo 
---
 drivers/gpu/drm/drm_dp_helper.c | 51 +
 drivers/gpu/drm/drm_edid.c  | 23 ---
 include/drm/drm_connector.h |  6 
 include/drm/drm_dp_helper.h |  3 ++
 4 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index f629fc5494a4..1efd609df402 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -351,6 +351,57 @@ 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, test_resp = 0;
+
+   if (drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, _test_req, 
1) < 1) {
+   DRM_ERROR("DPCD failed read at register 0x%x\n", 
DP_DEVICE_SERVICE_IRQ_VECTOR);
+   return false;
+   }
+   auto_test_req &= DP_AUTOMATED_TEST_REQUEST;
+
+   if (drm_dp_dpcd_read(aux, DP_TEST_REQUEST, _edid_read, 1) < 1) {
+   DRM_ERROR("DPCD failed read at register 0x%x\n", 
DP_TEST_REQUEST);
+   return false;
+   }
+   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;
+   }
+
+   if (drm_dp_dpcd_write(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, 
_test_req, 1) < 1) {
+   DRM_ERROR("DPCD failed write at register 0x%x\n", 
DP_DEVICE_SERVICE_IRQ_VECTOR);
+   return false;
+   }
+
+   /* send back checksum for the last edid extension block data */
+   if (drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM, _edid_checksum, 
1) < 1) {
+   DRM_ERROR("DPCD failed write at register 0x%x\n", 
DP_TEST_EDID_CHECKSUM);
+   return false;
+   }
+
+   test_resp |= DP_TEST_EDID_CHECKSUM_WRITE;
+   if (drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, _resp, 1) < 1) {
+   DRM_ERROR("DPCD failed write at register 0x%x\n", 
DP_TEST_RESPONSE);
+   return false;
+   }
+
+   return true;
+}
+EXPORT_SYMBOL(drm_dp_send_real_edid_checksum);
+
 /**
  * drm_dp_downstream_max_clock() - extract branch device max
  * pixel rate for legacy VGA
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 99769d6c9f84..f064e75fb4c5 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1590,11 +1590,22 @@ static int validate_displayid(u8 *displayid, int 
length, int idx);
 static int drm_edid_block_checksum(const u8 *raw_edid)
 {
int i;
-   u8 csum = 0;
-   for (i = 0; i < EDID_LENGTH; i++)
+   u8 csum = 0, crc = 0;
+
+   for (i = 0; i < EDID_LENGTH - 1; i++)
csum += raw_edid[i];
 
-   return csum;
+   crc = 0x100 - csum;
+
+   return crc;
+}
+
+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)
@@ -1652,7 +1663,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;
 
@@ -1793,6 +1804,10 @@ static void connector_bad_edid(struct drm_connector 
*connector,
   u8 *edid, int num_blocks)
 {
int i;
+   u8 num_of_ext = edid[0x7e];
+
+   /* Calculate real

[Intel-gfx] [PATCH V5] drm: Add support for DP 1.4 Compliance edid corruption test

2020-01-31 Thread Jerry (Fangzhi) Zuo
Unlike DP 1.2 edid corruption test, DP 1.4 requires to calculate
real CRC value of the last edid data block, and write it back.
Current edid CRC calculates routine adds the last CRC byte,
and check if non-zero.

This behavior is not accurate; actually, we need to return
the actual CRC value when corruption is detected.
This commit changes this issue by returning the calculated CRC,
and initiate the required sequence.

Change since v5
- Obtain real CRC value before dumping bad edid

Change since v4
- Fix for CI.CHECKPATCH

Change since v3
- Fix a minor typo.

Change since v2
- Rewrite checksum computation routine to avoid duplicated code.
- Rename to avoid confusion.

Change since v1
- Have separate routine for returning real CRC.

Signed-off-by: Jerry (Fangzhi) Zuo 
---
 drivers/gpu/drm/drm_dp_helper.c | 35 +
 drivers/gpu/drm/drm_edid.c  | 23 ++
 include/drm/drm_connector.h |  6 ++
 include/drm/drm_dp_helper.h |  3 +++
 4 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index f629fc5494a4..18b285fa1a42 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -351,6 +351,41 @@ 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, test_resp = 0;
+
+   drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, _test_req, 1);
+   auto_test_req &= DP_AUTOMATED_TEST_REQUEST;
+
+   drm_dp_dpcd_read(aux, DP_TEST_REQUEST, _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, _test_req, 1);
+
+   /* send back checksum for the last edid extension block data */
+   drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM, _edid_checksum, 1);
+
+   test_resp |= DP_TEST_EDID_CHECKSUM_WRITE;
+   drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, _resp, 1);
+
+   return true;
+}
+EXPORT_SYMBOL(drm_dp_send_real_edid_checksum);
+
 /**
  * drm_dp_downstream_max_clock() - extract branch device max
  * pixel rate for legacy VGA
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 99769d6c9f84..f064e75fb4c5 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1590,11 +1590,22 @@ static int validate_displayid(u8 *displayid, int 
length, int idx);
 static int drm_edid_block_checksum(const u8 *raw_edid)
 {
int i;
-   u8 csum = 0;
-   for (i = 0; i < EDID_LENGTH; i++)
+   u8 csum = 0, crc = 0;
+
+   for (i = 0; i < EDID_LENGTH - 1; i++)
csum += raw_edid[i];
 
-   return csum;
+   crc = 0x100 - csum;
+
+   return crc;
+}
+
+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)
@@ -1652,7 +1663,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;
 
@@ -1793,6 +1804,10 @@ static void connector_bad_edid(struct drm_connector 
*connector,
   u8 *edid, int num_blocks)
 {
int i;
+   u8 num_of_ext = edid[0x7e];
+
+   /* Calculate real checksum for the last edid extension block data */
+   connector->real_edid_checksum = drm_edid_block_checksum(edid + 
num_of_ext * EDID_LENGTH);
 
if (connector->bad_edid_counter++ && !drm_debug_enabled(DRM_UT_KMS))
return;
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 2113500b4075..b3815371c271 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1357,6 +1357,12 @@ struct drm_connector {
 * rev1.1 4.2.2.6
 */
bool edid_corrupt;
+   /**
+* @real_edid_checksum: real edid checksum for corrupted edid block.
+* Required in Displayport 1.4 compliance testing
+* rev1.1 4.2.2.6
+*/
+   u8 real_edid_checksum;
 
/** @debugfs_entry

[Intel-gfx] [PATCH V4] drm: Add support for DP 1.4 Compliance edid corruption test

2019-12-09 Thread Jerry (Fangzhi) Zuo
Unlike DP 1.2 edid corruption test, DP 1.4 requires to calculate
real CRC value of the last edid data block, and write it back.
Current edid CRC calculates routine adds the last CRC byte,
and check if non-zero.

This behavior is not accurate; actually, we need to return
the actual CRC value when corruption is detected.
This commit changes this issue by returning the calculated CRC,
and initiate the required sequence.

Change since v4
- Fix for CI.CHECKPATCH

Change since v3
- Fix a minor typo.

Change since v2
- Rewrite checksum computation routine to avoid duplicated code.
- Rename to avoid confusion.

Change since v1
- Have separate routine for returning real CRC.

Signed-off-by: Jerry (Fangzhi) Zuo 
---
 drivers/gpu/drm/drm_dp_helper.c | 35 +
 drivers/gpu/drm/drm_edid.c  | 23 ++
 include/drm/drm_connector.h |  6 ++
 include/drm/drm_dp_helper.h |  3 +++
 4 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 2c7870aef469..85a777ce98ba 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -351,6 +351,41 @@ 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, test_resp = 0;
+
+   drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, _test_req, 1);
+   auto_test_req &= DP_AUTOMATED_TEST_REQUEST;
+
+   drm_dp_dpcd_read(aux, DP_TEST_REQUEST, _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, _test_req, 1);
+
+   /* send back checksum for the last edid extension block data */
+   drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM, _edid_checksum, 1);
+
+   test_resp |= DP_TEST_EDID_CHECKSUM_WRITE;
+   drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, _resp, 1);
+
+   return true;
+}
+EXPORT_SYMBOL(drm_dp_send_real_edid_checksum);
+
 /**
  * drm_dp_downstream_max_clock() - extract branch device max
  * pixel rate for legacy VGA
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 5b33b7cfd645..0e35405ecc74 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1450,11 +1450,22 @@ static int validate_displayid(u8 *displayid, int 
length, int idx);
 static int drm_edid_block_checksum(const u8 *raw_edid)
 {
int i;
-   u8 csum = 0;
-   for (i = 0; i < EDID_LENGTH; i++)
+   u8 csum = 0, crc = 0;
+
+   for (i = 0; i < EDID_LENGTH - 1; i++)
csum += raw_edid[i];
 
-   return csum;
+   crc = 0x100 - csum;
+
+   return crc;
+}
+
+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)
@@ -1512,7 +1523,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;
 
@@ -1653,6 +1664,7 @@ static void connector_bad_edid(struct drm_connector 
*connector,
   u8 *edid, int num_blocks)
 {
int i;
+   u8 num_of_ext = edid[0x7e];
 
if (connector->bad_edid_counter++ && !drm_debug_enabled(DRM_UT_KMS))
return;
@@ -1675,6 +1687,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 + 
num_of_ext * EDID_LENGTH);
 }
 
 /* Get override or firmware EDID */
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 5f8c3389d46f..b07d8276a58c 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1349,6 +1349,12 @@ struct drm_connector {
 * rev1.1 4.2.2.6
 */
bool edid_corrupt;
+   /**
+* @real_edid_checksum: real 

[Intel-gfx] [PATCH v4] drm: Add support for DP 1.4 Compliance edid corruption test

2019-12-05 Thread Jerry (Fangzhi) Zuo
Unlike DP 1.2 edid corruption test, DP 1.4 requires to calculate
real CRC value of the last edid data block, and write it back.
Current edid CRC calculates routine adds the last CRC byte,
and check if non-zero.

This behavior is not accurate; actually, we need to return
the actual CRC value when corruption is detected.
This commit changes this issue by returning the calculated CRC,
and initiate the required sequence.

Change since v3
- Fix a minor typo.

Change since v2
- Rewrite checksum computation routine to avoid duplicated code.
- Rename to avoid confusion.

Change since v1
- Have separate routine for returning real CRC.

Signed-off-by: Jerry (Fangzhi) Zuo 
---
 drivers/gpu/drm/drm_dp_helper.c | 35 +++
 drivers/gpu/drm/drm_edid.c  | 23 +++
 include/drm/drm_connector.h |  6 ++
 include/drm/drm_dp_helper.h |  3 +++
 4 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 2c7870aef469..c59f7c94ebf1 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -351,6 +351,41 @@ 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, test_resp = 0;
+
+   drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, _test_req, 1);
+   auto_test_req &= DP_AUTOMATED_TEST_REQUEST;
+
+   drm_dp_dpcd_read(aux, DP_TEST_REQUEST, _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, _test_req, 1);
+
+   /* send back checksum for the last edid extension block data */
+   drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM, _edid_checksum, 1);
+
+   test_resp |= DP_TEST_EDID_CHECKSUM_WRITE;
+   drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, _resp, 1);
+
+   return true;
+}
+EXPORT_SYMBOL(drm_dp_send_real_edid_checksum);
+
 /**
  * drm_dp_downstream_max_clock() - extract branch device max
  * pixel rate for legacy VGA
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 5b33b7cfd645..0e35405ecc74 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1450,11 +1450,22 @@ static int validate_displayid(u8 *displayid, int 
length, int idx);
 static int drm_edid_block_checksum(const u8 *raw_edid)
 {
int i;
-   u8 csum = 0;
-   for (i = 0; i < EDID_LENGTH; i++)
+   u8 csum = 0, crc = 0;
+
+   for (i = 0; i < EDID_LENGTH - 1; i++)
csum += raw_edid[i];
 
-   return csum;
+   crc = 0x100 - csum;
+
+   return crc;
+}
+
+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)
@@ -1512,7 +1523,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;
 
@@ -1653,6 +1664,7 @@ static void connector_bad_edid(struct drm_connector 
*connector,
   u8 *edid, int num_blocks)
 {
int i;
+   u8 num_of_ext = edid[0x7e];
 
if (connector->bad_edid_counter++ && !drm_debug_enabled(DRM_UT_KMS))
return;
@@ -1675,6 +1687,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 + 
num_of_ext * EDID_LENGTH);
 }
 
 /* Get override or firmware EDID */
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 5f8c3389d46f..86fc9f603fbc 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1349,6 +1349,12 @@ struct drm_connector {
 * rev1.1 4.2.2.6
 */
bool edid_corrupt;
+   /**
+   * @real_edid_checksum: real edid checksum value for corrupted edid 
block.

[Intel-gfx] [RESEND 0/2] Changes for DP 1.4 Compliance test 4.2.2.6

2019-12-02 Thread Jerry (Fangzhi) Zuo
Unlike DP 1.2 Compliance test 4.2.2.6, DP 1.4 requires to calculate real
CRC value of the last edid data block, and write it back.

Current edid CRC calculate routine adds the last CRC byte, and check if
non-zero or not. Need to return the actual CRC value when corruption is
detected.

[For CI]
Resend this patchset to intel gfx CI. 

Jerry (Fangzhi) Zuo (2):
  drm: Add support for DP 1.4 Compliance edid corruption test 4.2.2.6
  drm/amd/display: Hook up drm interface for DP 1.4 edid corruption test

 .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c  | 35 +
 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 ++
 5 files changed, 68 insertions(+), 31 deletions(-)

-- 
2.14.1

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

[Intel-gfx] [RESEND 1/2] drm: Add support for DP 1.4 Compliance edid corruption test 4.2.2.6

2019-12-02 Thread Jerry (Fangzhi) Zuo
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 
Reviewed-by: Harry Wentland 
---
 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, _test_req, 1);
+auto_test_req &= DP_AUTOMATED_TEST_REQUEST;
+
+drm_dp_dpcd_read(aux, DP_TEST_REQUEST, _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, _test_req, 
1);
+
+/* send back checksum for the last edid extension block data */
+drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM, _edid_checksum, 1);
+
+test_resp |= DP_TEST_EDID_CHECKSUM_WRITE;
+drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, _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_chec

[Intel-gfx] [RESEND 2/2] drm/amd/display: Hook up drm interface for DP 1.4 edid corruption test

2019-12-02 Thread Jerry (Fangzhi) Zuo
-v3: Rename to avoid confusion

Signed-off-by: Jerry (Fangzhi) Zuo 
Reviewed-by: Harry Wentland 
---
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c  | 35 +-
 1 file changed, 7 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 11e5784aa62a..927fdac77b6f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -575,6 +575,7 @@ enum dc_edid_status dm_helpers_read_local_edid(
struct dc_sink *sink)
 {
struct amdgpu_dm_connector *aconnector = link->priv;
+   struct drm_connector *connector = >base;
struct i2c_adapter *ddc;
int retry = 3;
enum dc_edid_status edid_status;
@@ -592,6 +593,12 @@ enum dc_edid_status dm_helpers_read_local_edid(
 
edid = drm_get_edid(>base, ddc);
 
+   if (link->aux_mode && connector->edid_corrupt)
+   
drm_dp_send_real_edid_checksum(>dm_dp_aux.aux, 
connector->real_edid_checksum);
+
+   if (!edid && connector->edid_corrupt)
+   return EDID_BAD_CHECKSUM;
+
if (!edid)
return EDID_NO_RESPONSE;
 
@@ -612,34 +619,6 @@ enum dc_edid_status dm_helpers_read_local_edid(
DRM_ERROR("EDID err: %d, on connector: %s",
edid_status,
aconnector->base.name);
-   if (link->aux_mode) {
-   union test_request test_request = { {0} };
-   union test_response test_response = { {0} };
-
-   dm_helpers_dp_read_dpcd(ctx,
-   link,
-   DP_TEST_REQUEST,
-   _request.raw,
-   sizeof(union test_request));
-
-   if (!test_request.bits.EDID_READ)
-   return edid_status;
-
-   test_response.bits.EDID_CHECKSUM_WRITE = 1;
-
-   dm_helpers_dp_write_dpcd(ctx,
-   link,
-   DP_TEST_EDID_CHECKSUM,
-   
>dc_edid.raw_edid[sink->dc_edid.length-1],
-   1);
-
-   dm_helpers_dp_write_dpcd(ctx,
-   link,
-   DP_TEST_RESPONSE,
-   _response.raw,
-   sizeof(test_response));
-
-   }
 
return edid_status;
 }
-- 
2.14.1

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx