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 <chandanu@codeaurora.org>
Signed-off-by: Tatenda Chipeperekwa <tatendac@codeaurora.org>
This commit is contained in:
Chandan Uddaraju 2016-07-27 13:35:52 -07:00 committed by Tatenda Chipeperekwa
parent b6b15c3385
commit b62bc857c7
4 changed files with 81 additions and 72 deletions

View file

@ -42,43 +42,6 @@
#define VDDA_UA_ON_LOAD 100000 /* uA units */ #define VDDA_UA_ON_LOAD 100000 /* uA units */
#define VDDA_UA_OFF_LOAD 100 /* 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, static void mdss_dp_put_dt_clk_data(struct device *dev,
struct dss_module_power *module_power) 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"); pr_err("Unabled to start core clocks\n");
return ret; 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); mdss_dp_hpd_configure(&dp_drv->ctrl_io, true);
orientation = usbpd_get_plug_orientation(dp_drv->pd); 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)) if (dp_drv->new_vic && (dp_drv->new_vic != dp_drv->vic))
dp_init_panel_info(dp_drv, dp_drv->new_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 = dp_drv->link_rate =
mdss_dp_gen_link_clk(&dp_drv->panel_data.panel_info, mdss_dp_gen_link_clk(&dp_drv->panel_data.panel_info,
dp_drv->dpcd.max_lane_count); dp_drv->dpcd.max_lane_count);
@ -1143,9 +1098,10 @@ static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
return -ENODEV; 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; 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; 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_ctrl_hw_version(&dp_drv->ctrl_io),
mdss_dp_get_phy_hw_version(&dp_drv->phy_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); ret = hdmi_edid_parser(dp_drv->panel_data.panel_info.edid_data);
if (ret) { if (ret) {
DEV_ERR("%s: edid parse failed\n", __func__); DEV_ERR("%s: edid parse failed\n", __func__);
goto edid_parser_error; goto edid_error;
} }
mdss_dp_send_cable_notification(dp_drv, true); mdss_dp_send_cable_notification(dp_drv, true);
return ret; return ret;
edid_parser_error: edid_error:
mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false); mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false);
clk_error: clk_error:
mdss_dp_regulator_ctrl(dp_drv, false); mdss_dp_regulator_ctrl(dp_drv, false);
@ -1422,7 +1391,7 @@ static void mdss_dp_event_work(struct work_struct *work)
switch (todo) { switch (todo) {
case EV_EDID_READ: case EV_EDID_READ:
mdss_dp_edid_read(dp, 0); mdss_dp_edid_read(dp);
break; break;
case EV_DPCD_CAP_READ: case EV_DPCD_CAP_READ:
mdss_dp_dpcd_cap_read(dp); mdss_dp_dpcd_cap_read(dp);

View file

@ -378,6 +378,8 @@ struct mdss_dp_drv_pdata {
char train_link_rate; /* X 27000000 for real rate */ char train_link_rate; /* X 27000000 for real rate */
char train_lane_cnt; char train_lane_cnt;
u8 *edid_buf;
u32 edid_buf_size;
struct edp_edid edid; struct edp_edid edid;
struct dpcd_cap dpcd; 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); void mdss_dp_dpcd_cap_read(struct mdss_dp_drv_pdata *dp);
int mdss_dp_dpcd_status_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); 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_i2c_handler(struct mdss_dp_drv_pdata *dp, u32 isr);
void dp_aux_native_handler(struct mdss_dp_drv_pdata *dp, u32 isr); void dp_aux_native_handler(struct mdss_dp_drv_pdata *dp, u32 isr);

View file

@ -665,7 +665,7 @@ static int dp_aux_chan_ready(struct mdss_dp_drv_pdata *ep)
char data = 0; char data = 0;
for (cnt = 5; cnt; cnt--) { 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); pr_debug("ret=%d\n", ret);
if (ret >= 0) if (ret >= 0)
break; break;
@ -680,43 +680,85 @@ static int dp_aux_chan_ready(struct mdss_dp_drv_pdata *ep)
return 0; 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; struct edp_buf *rp;
int cnt, rlen; int cnt, rlen;
int ret = 0; int ret = 0;
int blk_num = 0;
ret = dp_aux_chan_ready(ep); ret = dp_aux_chan_ready(dp);
if (ret) { if (ret) {
pr_err("aux chan NOT ready\n"); pr_err("aux chan NOT ready\n");
return ret; return ret;
} }
for (cnt = 5; cnt; cnt--) { 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) { 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)) if (!dp_edid_buf_error(rp->data, rp->len))
break; break;
} }
} }
if (cnt <= 0) { if ((cnt <= 0) && (rlen != EDID_BLOCK_SIZE)) {
pr_err("Failed\n"); pr_err("Read failed. rlen=%d\n", rlen);
return -EINVAL; return -EINVAL;
} }
dp_extract_edid_manufacturer(&ep->edid, rp->data); rp = &dp->rxp;
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);
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, 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 mdss_dp_link_train(struct mdss_dp_drv_pdata *ep)
{ {
int ret; int ret;

View file

@ -86,6 +86,7 @@
#define TXn_TX_DRV_LVL 0x001C #define TXn_TX_DRV_LVL 0x001C
#define TCSR_USB3_DP_PHYMODE 0x48 #define TCSR_USB3_DP_PHYMODE 0x48
#define EDID_START_ADDRESS 0x50
struct lane_mapping { struct lane_mapping {
char lane0; char lane0;