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

Commit 732cfdd3 authored by Padmanabhan Komanduru's avatar Padmanabhan Komanduru Committed by Gerrit - the friendly Code Review server
Browse files

msm: mdss: add support for handling LP_RX_TIMEOUT error



During ESD attack, sometimes the panel DDIC might not respond
to the ESD read command. This causes the data lane0 to get stuck
in reverse transmission causing DSI HS FIFO overflow errors
continuously in forward transmission. Enable the error interrupt
generation for LP_RX_TIMEOUT to handle this. Reset the DSI controller
and force DSI lanes to LP-11 to recover from this situation.

Crs-Fixed: 863383
Change-Id: Iee7d5e0c85fb77b9c8f899e569e37b54a100f67a
Signed-off-by: default avatarPadmanabhan Komanduru <pkomandu@codeaurora.org>
Signed-off-by: default avatarSandeep Panda <spanda@codeaurora.org>
Signed-off-by: default avatarSiddhartha Agrawal <agrawals@codeaurora.org>
Signed-off-by: default avatarVinu Deokaran <vinud@codeaurora.org>
parent e949c31b
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -195,6 +195,7 @@ enum dsi_pm_type {


#define DSI_DATA_LANES_STOP_STATE	0xF
#define DSI_DATA_LANES_STOP_STATE	0xF
#define DSI_CLK_LANE_STOP_STATE		BIT(4)
#define DSI_CLK_LANE_STOP_STATE		BIT(4)
#define DSI_DATA_LANES_ENABLED		0xF0


/* offsets for dynamic refresh */
/* offsets for dynamic refresh */
#define DSI_DYNAMIC_REFRESH_CTRL		0x200
#define DSI_DYNAMIC_REFRESH_CTRL		0x200
@@ -333,6 +334,7 @@ struct panel_horizontal_idle {
#define DSI_EV_MDP_FIFO_UNDERFLOW	0x0002
#define DSI_EV_MDP_FIFO_UNDERFLOW	0x0002
#define DSI_EV_DSI_FIFO_EMPTY		0x0004
#define DSI_EV_DSI_FIFO_EMPTY		0x0004
#define DSI_EV_DLNx_FIFO_OVERFLOW	0x0008
#define DSI_EV_DLNx_FIFO_OVERFLOW	0x0008
#define DSI_EV_LP_RX_TIMEOUT		0x0010
#define DSI_EV_STOP_HS_CLK_LANE		0x40000000
#define DSI_EV_STOP_HS_CLK_LANE		0x40000000
#define DSI_EV_MDP_BUSY_RELEASE		0x80000000
#define DSI_EV_MDP_BUSY_RELEASE		0x80000000


+31 −11
Original line number Original line Diff line number Diff line
@@ -389,7 +389,7 @@ void mdss_dsi_host_init(struct mdss_panel_data *pdata)


	/* allow only ack-err-status  to generate interrupt */
	/* allow only ack-err-status  to generate interrupt */
	/* DSI_ERR_INT_MASK0 */
	/* DSI_ERR_INT_MASK0 */
	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x010c, 0x03f03fe0);
	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x010c, 0x03f03fc0);


	intr_ctrl |= DSI_INTR_ERROR_MASK;
	intr_ctrl |= DSI_INTR_ERROR_MASK;
	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0110,
	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0110,
@@ -632,9 +632,9 @@ static void mdss_dsi_cmd_stop_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl)
	mdss_dsi_stop_hs_clk_lane(ctrl);
	mdss_dsi_stop_hs_clk_lane(ctrl);
}
}


static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl)
static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl, u32 event)
{
{
	u32 data0, data1;
	u32 data0, data1, mask = 0, data_lane_en = 0;
	struct mdss_dsi_ctrl_pdata *ctrl0, *ctrl1;
	struct mdss_dsi_ctrl_pdata *ctrl0, *ctrl1;
	u32 ln0, ln1, ln_ctrl0, ln_ctrl1, i;
	u32 ln0, ln1, ln_ctrl0, ln_ctrl1, i;
	/*
	/*
@@ -644,6 +644,14 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl)
	u32 loop = 10, u_dly = 200;
	u32 loop = 10, u_dly = 200;
	pr_debug("%s: MDSS DSI CTRL and PHY reset. ctrl-num = %d\n",
	pr_debug("%s: MDSS DSI CTRL and PHY reset. ctrl-num = %d\n",
					__func__, ctrl->ndx);
					__func__, ctrl->ndx);
	if (event == DSI_EV_DLNx_FIFO_OVERFLOW) {
		mask = BIT(20); /* clock lane only for overflow recovery */
	} else if (event == DSI_EV_LP_RX_TIMEOUT) {
		data_lane_en = (MIPI_INP(ctrl->ctrl_base + 0x0004) &
			DSI_DATA_LANES_ENABLED) >> 4;
		/* clock and data lanes for LP_RX_TO recovery */
		mask = BIT(20) | (data_lane_en << 16);
	}


	if (mdss_dsi_is_hw_config_split(ctrl->shared_data)) {
	if (mdss_dsi_is_hw_config_split(ctrl->shared_data)) {
		pr_debug("%s: Split display enabled\n", __func__);
		pr_debug("%s: Split display enabled\n", __func__);
@@ -700,8 +708,8 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl)
			 __func__, ln0, ln1);
			 __func__, ln0, ln1);
		ln_ctrl0 = MIPI_INP(ctrl0->ctrl_base + 0x00ac);
		ln_ctrl0 = MIPI_INP(ctrl0->ctrl_base + 0x00ac);
		ln_ctrl1 = MIPI_INP(ctrl1->ctrl_base + 0x00ac);
		ln_ctrl1 = MIPI_INP(ctrl1->ctrl_base + 0x00ac);
		MIPI_OUTP(ctrl0->ctrl_base + 0x0ac, ln_ctrl0 | BIT(20));
		MIPI_OUTP(ctrl0->ctrl_base + 0x0ac, ln_ctrl0 | mask);
		MIPI_OUTP(ctrl1->ctrl_base + 0x0ac, ln_ctrl1 | BIT(20));
		MIPI_OUTP(ctrl1->ctrl_base + 0x0ac, ln_ctrl1 | mask);
		ln_ctrl0 = MIPI_INP(ctrl0->ctrl_base + 0x00ac);
		ln_ctrl0 = MIPI_INP(ctrl0->ctrl_base + 0x00ac);
		ln_ctrl1 = MIPI_INP(ctrl1->ctrl_base + 0x00ac);
		ln_ctrl1 = MIPI_INP(ctrl1->ctrl_base + 0x00ac);
		for (i = 0; i < loop; i++) {
		for (i = 0; i < loop; i++) {
@@ -722,8 +730,8 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl)
		}
		}
		pr_debug("%s: lane ctrl, ctrl0 = 0x%x, ctrl1 = 0x%x\n",
		pr_debug("%s: lane ctrl, ctrl0 = 0x%x, ctrl1 = 0x%x\n",
			 __func__, ln0, ln1);
			 __func__, ln0, ln1);
		MIPI_OUTP(ctrl0->ctrl_base + 0x0ac, ln_ctrl0 & ~BIT(20));
		MIPI_OUTP(ctrl0->ctrl_base + 0x0ac, ln_ctrl0 & ~mask);
		MIPI_OUTP(ctrl1->ctrl_base + 0x0ac, ln_ctrl1 & ~BIT(20));
		MIPI_OUTP(ctrl1->ctrl_base + 0x0ac, ln_ctrl1 & ~mask);


		/* Enable Video mode for DSI controller */
		/* Enable Video mode for DSI controller */
		MIPI_OUTP(ctrl0->ctrl_base + 0x004, data0);
		MIPI_OUTP(ctrl0->ctrl_base + 0x004, data0);
@@ -775,7 +783,7 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl)
		pr_debug("%s: lane status, ctrl = 0x%x\n",
		pr_debug("%s: lane status, ctrl = 0x%x\n",
			 __func__, ln0);
			 __func__, ln0);
		ln_ctrl0 = MIPI_INP(ctrl->ctrl_base + 0x00ac);
		ln_ctrl0 = MIPI_INP(ctrl->ctrl_base + 0x00ac);
		MIPI_OUTP(ctrl->ctrl_base + 0x0ac, ln_ctrl0 | BIT(20));
		MIPI_OUTP(ctrl->ctrl_base + 0x0ac, ln_ctrl0 | mask);
		ln_ctrl0 = MIPI_INP(ctrl->ctrl_base + 0x00ac);
		ln_ctrl0 = MIPI_INP(ctrl->ctrl_base + 0x00ac);
		for (i = 0; i < loop; i++) {
		for (i = 0; i < loop; i++) {
			ln0 = MIPI_INP(ctrl->ctrl_base + 0x00a8);
			ln0 = MIPI_INP(ctrl->ctrl_base + 0x00a8);
@@ -793,7 +801,7 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl)
		}
		}
		pr_debug("%s: lane status = 0x%x\n",
		pr_debug("%s: lane status = 0x%x\n",
			 __func__, ln0);
			 __func__, ln0);
		MIPI_OUTP(ctrl->ctrl_base + 0x0ac, ln_ctrl0 & ~BIT(20));
		MIPI_OUTP(ctrl->ctrl_base + 0x0ac, ln_ctrl0 & ~mask);


		/* Enable Video mode for DSI controller */
		/* Enable Video mode for DSI controller */
		MIPI_OUTP(ctrl->ctrl_base + 0x004, data0);
		MIPI_OUTP(ctrl->ctrl_base + 0x004, data0);
@@ -2326,7 +2334,8 @@ static int dsi_event_thread(void *data)
				mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
				mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
						  MDSS_DSI_ALL_CLKS,
						  MDSS_DSI_ALL_CLKS,
						  MDSS_DSI_CLK_ON);
						  MDSS_DSI_CLK_ON);
				mdss_dsi_ctl_phy_reset(ctrl);
				mdss_dsi_ctl_phy_reset(ctrl,
						DSI_EV_DLNx_FIFO_OVERFLOW);
				mdss_dsi_err_intr_ctrl(ctrl,
				mdss_dsi_err_intr_ctrl(ctrl,
						DSI_INTR_ERROR_MASK, 1);
						DSI_INTR_ERROR_MASK, 1);
				mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
				mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
@@ -2340,7 +2349,8 @@ static int dsi_event_thread(void *data)
				mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
				mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
						  MDSS_DSI_ALL_CLKS,
						  MDSS_DSI_ALL_CLKS,
						  MDSS_DSI_CLK_ON);
						  MDSS_DSI_CLK_ON);
				mdss_dsi_ctl_phy_reset(ctrl);
				mdss_dsi_ctl_phy_reset(ctrl,
						DSI_EV_DLNx_FIFO_OVERFLOW);
				mdss_dsi_err_intr_ctrl(ctrl,
				mdss_dsi_err_intr_ctrl(ctrl,
						DSI_INTR_ERROR_MASK, 1);
						DSI_INTR_ERROR_MASK, 1);
				mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
				mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
@@ -2369,6 +2379,14 @@ static int dsi_event_thread(void *data)


		if (todo & DSI_EV_STOP_HS_CLK_LANE)
		if (todo & DSI_EV_STOP_HS_CLK_LANE)
			mdss_dsi_stop_hs_clk_lane(ctrl);
			mdss_dsi_stop_hs_clk_lane(ctrl);

		if (todo & DSI_EV_LP_RX_TIMEOUT) {
			mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
					  MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON);
			mdss_dsi_ctl_phy_reset(ctrl, DSI_EV_LP_RX_TIMEOUT);
			mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
					  MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF);
		}
	}
	}


	return 0;
	return 0;
@@ -2412,6 +2430,8 @@ void mdss_dsi_timeout_status(struct mdss_dsi_ctrl_pdata *ctrl)


	if (status & 0x0111) {
	if (status & 0x0111) {
		MIPI_OUTP(base + 0x00c0, status);
		MIPI_OUTP(base + 0x00c0, status);
		if (status & 0x0010)
			dsi_send_events(ctrl, DSI_EV_LP_RX_TIMEOUT, 0);
		pr_err("%s: status=%x\n", __func__, status);
		pr_err("%s: status=%x\n", __func__, status);
	}
	}
}
}