From b62bc857c7e2a3a58e604111200e95db571eaa66 Mon Sep 17 00:00:00 2001 From: Chandan Uddaraju Date: Wed, 27 Jul 2016 13:35:52 -0700 Subject: [PATCH] mdss: display-port: add support for edid read Add support to read EDID data using the aux channel. Remove the stored EDID buffer and use the retrieved EDID data to initialize the DP controller. CRs-Fixed: 1009284 Change-Id: I93b43be6c2ca50796148898f5210c5b4d13b6f24 Signed-off-by: Chandan Uddaraju Signed-off-by: Tatenda Chipeperekwa --- drivers/video/fbdev/msm/mdss_dp.c | 69 +++++++--------------- drivers/video/fbdev/msm/mdss_dp.h | 4 +- drivers/video/fbdev/msm/mdss_dp_aux.c | 79 +++++++++++++++++++------- drivers/video/fbdev/msm/mdss_dp_util.h | 1 + 4 files changed, 81 insertions(+), 72 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index 0ac5ef4f750c..e0dd3f5d5635 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -42,43 +42,6 @@ #define VDDA_UA_ON_LOAD 100000 /* uA units */ #define VDDA_UA_OFF_LOAD 100 /* uA units */ -static char edid_buf1[] = { - 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x22, 0xf0, 0x52, 0x29, 0x01, 0x01, 0x01, 0x01, - 0x16, 0x16, 0x01, 0x03, 0x80, 0x30, 0x1b, 0x78, - 0x2e, 0xee, 0x95, 0xa3, 0x54, 0x4c, 0x99, 0x26, - 0x0f, 0x50, 0x54, 0xa1, 0x08, 0x00, 0xd1, 0xc0, - 0x81, 0xc0, 0xa9, 0xc0, 0xb3, 0x00, 0x95, 0x00, - 0x81, 0x40, 0x81, 0x80, 0x01, 0x01, 0x02, 0x3a, - 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, - 0x45, 0x00, 0xdb, 0x0b, 0x11, 0x00, 0x00, 0x1e, - 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, 0x4c, 0x18, - 0x5e, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x48, - 0x50, 0x20, 0x5a, 0x52, 0x32, 0x32, 0x34, 0x30, - 0x77, 0x0a, 0x20, 0x20, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x43, 0x4e, 0x34, 0x32, 0x32, 0x32, 0x30, - 0x30, 0x33, 0x46, 0x0a, 0x20, 0x20, 0x01, 0xb1, - - 0x02, 0x03, 0x17, 0xb1, 0x4c, 0x90, 0x1f, 0x05, - 0x14, 0x04, 0x13, 0x03, 0x02, 0x07, 0x06, 0x12, - 0x01, 0x65, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x02, - 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, - 0x2c, 0x45, 0x00, 0xdb, 0x0b, 0x11, 0x00, 0x00, - 0x1e, 0x02, 0x3a, 0x80, 0xd0, 0x72, 0x38, 0x2d, - 0x40, 0x10, 0x2c, 0x45, 0x80, 0xdb, 0x0b, 0x11, - 0x00, 0x00, 0x1e, 0x01, 0x1d, 0x00, 0x72, 0x51, - 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0xdb, - 0x0b, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d, 0x00, - 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28, 0x55, - 0x40, 0xdb, 0x0b, 0x11, 0x00, 0x00, 0x1e, 0x8c, - 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, - 0x3e, 0x96, 0x00, 0xdb, 0x0b, 0x11, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b -}; - - static void mdss_dp_put_dt_clk_data(struct device *dev, struct dss_module_power *module_power) { @@ -945,9 +908,6 @@ int mdss_dp_on(struct mdss_panel_data *pdata) pr_err("Unabled to start core clocks\n"); return ret; } - mdss_dp_phy_reset(&dp_drv->ctrl_io); - mdss_dp_aux_reset(&dp_drv->ctrl_io); - mdss_dp_aux_ctrl(&dp_drv->ctrl_io, true); mdss_dp_hpd_configure(&dp_drv->ctrl_io, true); orientation = usbpd_get_plug_orientation(dp_drv->pd); @@ -971,11 +931,6 @@ int mdss_dp_on(struct mdss_panel_data *pdata) if (dp_drv->new_vic && (dp_drv->new_vic != dp_drv->vic)) dp_init_panel_info(dp_drv, dp_drv->new_vic); - mdss_dp_phy_aux_setup(&dp_drv->phy_io); - - mdss_dp_irq_enable(dp_drv); - pr_debug("irq enabled\n"); - mdss_dp_dpcd_cap_read(dp_drv); dp_drv->link_rate = mdss_dp_gen_link_clk(&dp_drv->panel_data.panel_info, dp_drv->dpcd.max_lane_count); @@ -1143,9 +1098,10 @@ static int mdss_dp_edid_init(struct mdss_panel_data *pdata) return -ENODEV; } - /* Use the existing EDID buffer for 1080p */ - memcpy(edid_init_data.buf, edid_buf1, sizeof(edid_buf1)); dp_drv->panel_data.panel_info.edid_data = edid_data; + /* initialize EDID buffer pointers */ + dp_drv->edid_buf = edid_init_data.buf; + dp_drv->edid_buf_size = edid_init_data.buf_size; return 0; } @@ -1189,17 +1145,30 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata) mdss_dp_get_ctrl_hw_version(&dp_drv->ctrl_io), mdss_dp_get_phy_hw_version(&dp_drv->phy_io)); + mdss_dp_phy_aux_setup(&dp_drv->phy_io); + + mdss_dp_irq_enable(dp_drv); + pr_debug("irq enabled\n"); + mdss_dp_dpcd_cap_read(dp_drv); + + ret = mdss_dp_edid_read(dp_drv); + if (ret) + goto edid_error; + + pr_debug("edid_read success. buf_size=%d\n", + dp_drv->edid_buf_size); + ret = hdmi_edid_parser(dp_drv->panel_data.panel_info.edid_data); if (ret) { DEV_ERR("%s: edid parse failed\n", __func__); - goto edid_parser_error; + goto edid_error; } mdss_dp_send_cable_notification(dp_drv, true); return ret; -edid_parser_error: +edid_error: mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false); clk_error: mdss_dp_regulator_ctrl(dp_drv, false); @@ -1422,7 +1391,7 @@ static void mdss_dp_event_work(struct work_struct *work) switch (todo) { case EV_EDID_READ: - mdss_dp_edid_read(dp, 0); + mdss_dp_edid_read(dp); break; case EV_DPCD_CAP_READ: mdss_dp_dpcd_cap_read(dp); diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index 03646cd7cc65..a8bb2ab5d343 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -378,6 +378,8 @@ struct mdss_dp_drv_pdata { char train_link_rate; /* X 27000000 for real rate */ char train_lane_cnt; + u8 *edid_buf; + u32 edid_buf_size; struct edp_edid edid; struct dpcd_cap dpcd; @@ -464,7 +466,7 @@ void mdss_dp_phy_initialize(struct mdss_dp_drv_pdata *dp); void mdss_dp_dpcd_cap_read(struct mdss_dp_drv_pdata *dp); int mdss_dp_dpcd_status_read(struct mdss_dp_drv_pdata *dp); -void mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp, int block); +int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp); int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp); void dp_aux_i2c_handler(struct mdss_dp_drv_pdata *dp, u32 isr); void dp_aux_native_handler(struct mdss_dp_drv_pdata *dp, u32 isr); diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c index 7b14a7efb9dc..dfba02871649 100644 --- a/drivers/video/fbdev/msm/mdss_dp_aux.c +++ b/drivers/video/fbdev/msm/mdss_dp_aux.c @@ -665,7 +665,7 @@ static int dp_aux_chan_ready(struct mdss_dp_drv_pdata *ep) char data = 0; for (cnt = 5; cnt; cnt--) { - ret = dp_aux_write_buf(ep, 0x50, &data, 1, 1); + ret = dp_aux_write_buf(ep, EDID_START_ADDRESS, &data, 1, 1); pr_debug("ret=%d\n", ret); if (ret >= 0) break; @@ -680,43 +680,85 @@ static int dp_aux_chan_ready(struct mdss_dp_drv_pdata *ep) return 0; } -static int dp_sink_edid_read(struct mdss_dp_drv_pdata *ep, int block) +int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp) { struct edp_buf *rp; int cnt, rlen; int ret = 0; + int blk_num = 0; - ret = dp_aux_chan_ready(ep); + ret = dp_aux_chan_ready(dp); if (ret) { pr_err("aux chan NOT ready\n"); return ret; } for (cnt = 5; cnt; cnt--) { - rlen = dp_aux_read_buf(ep, 0x50, 128, 1); + rlen = dp_aux_read_buf + (dp, EDID_START_ADDRESS, EDID_BLOCK_SIZE, 1); if (rlen > 0) { - pr_debug("rlen=%d\n", rlen); + pr_debug("cnt=%d, block=%d, rlen=%d\n", + cnt, blk_num, rlen); - rp = &ep->rxp; + rp = &dp->rxp; if (!dp_edid_buf_error(rp->data, rp->len)) break; } } - if (cnt <= 0) { - pr_err("Failed\n"); + if ((cnt <= 0) && (rlen != EDID_BLOCK_SIZE)) { + pr_err("Read failed. rlen=%d\n", rlen); return -EINVAL; } - dp_extract_edid_manufacturer(&ep->edid, rp->data); - dp_extract_edid_product(&ep->edid, rp->data); - dp_extract_edid_version(&ep->edid, rp->data); - dp_extract_edid_ext_block_cnt(&ep->edid, rp->data); - dp_extract_edid_video_support(&ep->edid, rp->data); - dp_extract_edid_feature(&ep->edid, rp->data); - dp_extract_edid_detailed_timing_description(&ep->edid, rp->data); + rp = &dp->rxp; - return 128; + dp_extract_edid_manufacturer(&dp->edid, rp->data); + dp_extract_edid_product(&dp->edid, rp->data); + dp_extract_edid_version(&dp->edid, rp->data); + dp_extract_edid_ext_block_cnt(&dp->edid, rp->data); + dp_extract_edid_video_support(&dp->edid, rp->data); + dp_extract_edid_feature(&dp->edid, rp->data); + dp_extract_edid_detailed_timing_description(&dp->edid, rp->data); + /* for the first block initialize the edid buffer size */ + dp->edid_buf_size = 0; + + pr_debug("edid extension = %d\n", + dp->edid.ext_block_cnt); + + memcpy(dp->edid_buf, rp->data, EDID_BLOCK_SIZE); + dp->edid_buf_size += EDID_BLOCK_SIZE; + + if (!dp->edid.ext_block_cnt) + return 0; + + for (blk_num = 1; blk_num <= dp->edid.ext_block_cnt; + blk_num++) { + for (cnt = 5; cnt; cnt--) { + rlen = dp_aux_read_buf + (dp, EDID_START_ADDRESS + + (blk_num * EDID_BLOCK_SIZE), + EDID_BLOCK_SIZE, 1); + if (rlen > 0) { + pr_debug("cnt=%d, blk_num=%d, rlen=%d\n", + cnt, blk_num, rlen); + rp = &dp->rxp; + if (!dp_edid_buf_error(rp->data, rp->len)) + break; + } + } + + if ((cnt <= 0) && (rlen != EDID_BLOCK_SIZE)) { + pr_err("Read failed. rlen=%d\n", rlen); + return -EINVAL; + } + + memcpy(dp->edid_buf + (blk_num * EDID_BLOCK_SIZE), + rp->data, EDID_BLOCK_SIZE); + dp->edid_buf_size += EDID_BLOCK_SIZE; + } + + return 0; } static void dp_sink_capability_read(struct mdss_dp_drv_pdata *ep, @@ -1357,11 +1399,6 @@ void mdss_dp_fill_link_cfg(struct mdss_dp_drv_pdata *ep) } -void mdss_dp_edid_read(struct mdss_dp_drv_pdata *ep, int block) -{ - dp_sink_edid_read(ep, block); -} - int mdss_dp_link_train(struct mdss_dp_drv_pdata *ep) { int ret; diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h index 8ef00dd7248e..2079dba2a357 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.h +++ b/drivers/video/fbdev/msm/mdss_dp_util.h @@ -86,6 +86,7 @@ #define TXn_TX_DRV_LVL 0x001C #define TCSR_USB3_DP_PHYMODE 0x48 +#define EDID_START_ADDRESS 0x50 struct lane_mapping { char lane0;