Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b62bc857 authored by Chandan Uddaraju's avatar Chandan Uddaraju Committed by Tatenda Chipeperekwa
Browse files

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: default avatarChandan Uddaraju <chandanu@codeaurora.org>
Signed-off-by: default avatarTatenda Chipeperekwa <tatendac@codeaurora.org>
parent b6b15c33
Loading
Loading
Loading
Loading
+19 −50
Original line number Diff line number Diff line
@@ -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);
+3 −1
Original line number Diff line number Diff line
@@ -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);
+58 −21
Original line number Diff line number Diff line
@@ -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;

	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;

	return 128;
	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;
+1 −0
Original line number Diff line number Diff line
@@ -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;