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 Signed-off-by: Jerry (Fangzhi) Zuo <Jerry.Zuo@xxxxxxx> --- 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..75bdffd840c6 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 + * @bad_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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel