diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index da3fd3b9c133..068be4fdf602 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -513,16 +513,22 @@ enum dp_lane_count { }; enum test_response { - TEST_NACK = 0x0, - TEST_ACK = 0x1, + TEST_ACK = 0x1, + TEST_NACK = 0x2, + TEST_EDID_CHECKSUM_WRITE = 0x4, }; static inline char *mdss_dp_get_test_response(u32 test_response) { switch (test_response) { - case TEST_NACK: return DP_ENUM_STR(TEST_NACK); - case TEST_ACK: return DP_ENUM_STR(TEST_ACK); - default: return "unknown"; + case TEST_NACK: + return DP_ENUM_STR(TEST_NACK); + case TEST_ACK: + return DP_ENUM_STR(TEST_ACK); + case TEST_EDID_CHECKSUM_WRITE: + return DP_ENUM_STR(TEST_EDID_CHECKSUM_WRITE); + default: + return "unknown"; } } diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c index b64518194926..90afae40faa1 100644 --- a/drivers/video/fbdev/msm/mdss_dp_aux.c +++ b/drivers/video/fbdev/msm/mdss_dp_aux.c @@ -34,6 +34,8 @@ #include "mdss_dp.h" #include "mdss_dp_util.h" +static void dp_sink_parse_test_request(struct mdss_dp_drv_pdata *ep); + /* * edp buffer operation */ @@ -721,6 +723,20 @@ static int dp_aux_chan_ready(struct mdss_dp_drv_pdata *ep) return 0; } +static void dp_aux_send_checksum(struct mdss_dp_drv_pdata *dp, u32 checksum) +{ + char data[4]; + + data[0] = checksum; + pr_debug("writing checksum %d\n", data[0]); + dp_aux_write_buf(dp, 0x261, data, 1, 0); + + data[0] = TEST_EDID_CHECKSUM_WRITE; + pr_debug("sending test response %s\n", + mdss_dp_get_test_response(data[0])); + dp_aux_write_buf(dp, 0x260, data, 1, 0); +} + int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp) { struct edp_buf *rp = &dp->rxp; @@ -728,6 +744,7 @@ int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp) int edid_blk = 0, blk_num = 0, retries = 10; bool edid_parsing_done = false; const u8 cea_tag = 0x02; + u32 checksum = 0; ret = dp_aux_chan_ready(dp); if (ret) { @@ -735,6 +752,12 @@ int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp) return ret; } + /** + * Parse the test request vector to see whether there is a + * TEST_EDID_READ test request. + */ + dp_sink_parse_test_request(dp); + do { rlen = dp_aux_read_buf(dp, EDID_START_ADDRESS + (blk_num * EDID_BLOCK_SIZE), @@ -765,6 +788,7 @@ int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp) rp->data); edid_parsing_done = true; + checksum = rp->data[rp->len - 1]; } else { edid_blk++; blk_num++; @@ -783,9 +807,16 @@ int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp) rp->data, EDID_BLOCK_SIZE); if (edid_blk == dp->edid.ext_block_cnt) - return 0; + goto end; } while (retries--); +end: + if (dp->test_data.test_requested == TEST_EDID_READ) { + pr_debug("sending checksum %d\n", checksum); + dp_aux_send_checksum(dp, checksum); + dp->test_data = (const struct dpcd_test_request){ 0 }; + } + return 0; } @@ -1141,7 +1172,8 @@ static void dp_sink_parse_sink_count(struct mdss_dp_drv_pdata *ep) */ static bool dp_is_test_supported(u32 test_requested) { - return test_requested == TEST_LINK_TRAINING; + return (test_requested == TEST_LINK_TRAINING) || + (test_requested == TEST_EDID_READ); } /**