diff options
| author | Padmanabhan Komanduru <pkomandu@codeaurora.org> | 2015-03-31 18:34:16 +0530 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:44:19 -0700 |
| commit | 1fae88febd6504b2a6a6701182663cc41df22bfa (patch) | |
| tree | 3641259e21252f464674fef7ff3aa997c863effd /drivers/video/fbdev | |
| parent | 44d78c021c2f457d7096c002bcef3cce295f7bb0 (diff) | |
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: Padmanabhan Komanduru <pkomandu@codeaurora.org>
Signed-off-by: Sandeep Panda <spanda@codeaurora.org>
Signed-off-by: Siddhartha Agrawal <agrawals@codeaurora.org>
Signed-off-by: Vinu Deokaran <vinud@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.h | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_host.c | 42 |
2 files changed, 33 insertions, 11 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index a9367763baba..b73776e2b040 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -195,6 +195,7 @@ enum dsi_pm_type { #define DSI_DATA_LANES_STOP_STATE 0xF #define DSI_CLK_LANE_STOP_STATE BIT(4) +#define DSI_DATA_LANES_ENABLED 0xF0 /* offsets for dynamic refresh */ #define DSI_DYNAMIC_REFRESH_CTRL 0x200 @@ -333,6 +334,7 @@ struct panel_horizontal_idle { #define DSI_EV_MDP_FIFO_UNDERFLOW 0x0002 #define DSI_EV_DSI_FIFO_EMPTY 0x0004 #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_MDP_BUSY_RELEASE 0x80000000 diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index 839fd3056e28..c0541c7c22ae 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -389,7 +389,7 @@ void mdss_dsi_host_init(struct mdss_panel_data *pdata) /* allow only ack-err-status to generate interrupt */ /* 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; 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); } -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; 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; pr_debug("%s: MDSS DSI CTRL and PHY reset. ctrl-num = %d\n", __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)) { 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); ln_ctrl0 = MIPI_INP(ctrl0->ctrl_base + 0x00ac); ln_ctrl1 = MIPI_INP(ctrl1->ctrl_base + 0x00ac); - MIPI_OUTP(ctrl0->ctrl_base + 0x0ac, ln_ctrl0 | BIT(20)); - MIPI_OUTP(ctrl1->ctrl_base + 0x0ac, ln_ctrl1 | BIT(20)); + MIPI_OUTP(ctrl0->ctrl_base + 0x0ac, ln_ctrl0 | mask); + MIPI_OUTP(ctrl1->ctrl_base + 0x0ac, ln_ctrl1 | mask); ln_ctrl0 = MIPI_INP(ctrl0->ctrl_base + 0x00ac); ln_ctrl1 = MIPI_INP(ctrl1->ctrl_base + 0x00ac); 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", __func__, ln0, ln1); - MIPI_OUTP(ctrl0->ctrl_base + 0x0ac, ln_ctrl0 & ~BIT(20)); - MIPI_OUTP(ctrl1->ctrl_base + 0x0ac, ln_ctrl1 & ~BIT(20)); + MIPI_OUTP(ctrl0->ctrl_base + 0x0ac, ln_ctrl0 & ~mask); + MIPI_OUTP(ctrl1->ctrl_base + 0x0ac, ln_ctrl1 & ~mask); /* Enable Video mode for DSI controller */ 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", __func__, ln0); 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); for (i = 0; i < loop; i++) { 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", __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 */ 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_ALL_CLKS, 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, DSI_INTR_ERROR_MASK, 1); 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_ALL_CLKS, 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, DSI_INTR_ERROR_MASK, 1); 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) 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; @@ -2412,6 +2430,8 @@ void mdss_dsi_timeout_status(struct mdss_dsi_ctrl_pdata *ctrl) if (status & 0x0111) { 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); } } |
