Message ID | 20191101193839.25582-1-Jerry.Zuo@amd.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2,1/2] drm: Add support for DP 1.4 Compliance edid corruption test 4.2.2.6 | expand |
On 2019-11-01 3:38 p.m., Jerry (Fangzhi) Zuo wrote: > 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 > > Signed-off-by: Jerry (Fangzhi) Zuo <Jerry.Zuo@amd.com> > --- > drivers/gpu/drm/drm_dp_helper.c | 36 ++++++++++++++++++++++++++++++++++++ > drivers/gpu/drm/drm_edid.c | 14 ++++++++++++++ > include/drm/drm_connector.h | 7 +++++++ > include/drm/drm_dp_helper.h | 3 +++ > 4 files changed, 60 insertions(+) > > diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c > index ffc68d305afe..75dbd30c62a7 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_bad_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_bad_edid_checksum(struct drm_dp_aux *aux, > + u8 bad_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, &bad_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_bad_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..0598314e3f46 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -1354,6 +1354,17 @@ static int drm_edid_block_checksum(const u8 *raw_edid) > return csum; > } > > +static int drm_edid_block_real_checksum(const u8 *raw_edid) > +{ > + int i; > + u8 csum = 0; > + > + for (i = 0; i < EDID_LENGTH - 1; i++) > + csum += raw_edid[i]; > + > + return (0x100 - csum); > +} > + > static bool drm_edid_is_zero(const u8 *in_edid, int length) > { > if (memchr_inv(in_edid, 0, length)) > @@ -1572,6 +1583,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->bad_edid_checksum = drm_edid_block_real_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..8442461542b9 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; > + /** > + * @bad_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 bad_edid_checksum; This variable name confused me a bit. Maybe name this "computed_edid_checksum" to clarify that this is the EDID checksum that we've computed for the EDID, i.e. the correct one. > + > > /** @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..2a7e54bebb18 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_bad_edid_checksum(struct drm_dp_aux *aux, Same as before, might be good to name this drm_dp_send_computed_edid_checksum or something similar. Harry > + u8 bad_edid_checksum); > + > /* > * DisplayPort link > */ >
On Fri, 01 Nov 2019, "Jerry (Fangzhi) Zuo" <Jerry.Zuo@amd.com> wrote: > 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 > > Signed-off-by: Jerry (Fangzhi) Zuo <Jerry.Zuo@amd.com> > --- > drivers/gpu/drm/drm_dp_helper.c | 36 ++++++++++++++++++++++++++++++++++++ > drivers/gpu/drm/drm_edid.c | 14 ++++++++++++++ > include/drm/drm_connector.h | 7 +++++++ > include/drm/drm_dp_helper.h | 3 +++ > 4 files changed, 60 insertions(+) > > diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c > index ffc68d305afe..75dbd30c62a7 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_bad_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_bad_edid_checksum(struct drm_dp_aux *aux, > + u8 bad_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, &bad_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_bad_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..0598314e3f46 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -1354,6 +1354,17 @@ static int drm_edid_block_checksum(const u8 *raw_edid) > return csum; > } > > +static int drm_edid_block_real_checksum(const u8 *raw_edid) > +{ > + int i; > + u8 csum = 0; > + > + for (i = 0; i < EDID_LENGTH - 1; i++) > + csum += raw_edid[i]; > + > + return (0x100 - csum); Now you have two functions that have the loop to calculate checksums, which is not at all what I tried to tell you to do. I tried to suggest something like this: static int drm_edid_block_checksum(const u8 *raw_edid) { int i; u8 csum = 0; for (i = 0; i < EDID_LENGTH - 1; i++) csum += raw_edid[i]; return 0x100 - csum; } static int drm_edid_block_checksum_diff(const u8 *raw_edid) { u8 csum = drm_edid_block_checksum(raw_edid) + raw_edid[EDID_LENGTH - 1]; return csum; } Alternatively, you could have just the function to calculate the checksum, and then the check is comparing the calculated checksum against the checksum in the EDID. BR, Jani. > +} > + > static bool drm_edid_is_zero(const u8 *in_edid, int length) > { > if (memchr_inv(in_edid, 0, length)) > @@ -1572,6 +1583,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->bad_edid_checksum = drm_edid_block_real_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..8442461542b9 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; > + /** > + * @bad_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 bad_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..2a7e54bebb18 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_bad_edid_checksum(struct drm_dp_aux *aux, > + u8 bad_edid_checksum); > + > /* > * DisplayPort link > */
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index ffc68d305afe..75dbd30c62a7 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_bad_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_bad_edid_checksum(struct drm_dp_aux *aux, + u8 bad_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, &bad_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_bad_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..0598314e3f46 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1354,6 +1354,17 @@ static int drm_edid_block_checksum(const u8 *raw_edid) return csum; } +static int drm_edid_block_real_checksum(const u8 *raw_edid) +{ + int i; + u8 csum = 0; + + for (i = 0; i < EDID_LENGTH - 1; i++) + csum += raw_edid[i]; + + return (0x100 - csum); +} + static bool drm_edid_is_zero(const u8 *in_edid, int length) { if (memchr_inv(in_edid, 0, length)) @@ -1572,6 +1583,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->bad_edid_checksum = drm_edid_block_real_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..8442461542b9 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; + /** + * @bad_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 bad_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..2a7e54bebb18 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_bad_edid_checksum(struct drm_dp_aux *aux, + u8 bad_edid_checksum); + /* * DisplayPort link */
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 Signed-off-by: Jerry (Fangzhi) Zuo <Jerry.Zuo@amd.com> --- drivers/gpu/drm/drm_dp_helper.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_edid.c | 14 ++++++++++++++ include/drm/drm_connector.h | 7 +++++++ include/drm/drm_dp_helper.h | 3 +++ 4 files changed, 60 insertions(+)