diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index 46832edd5a62..bb962ef4a7b7 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -176,6 +176,9 @@ enum dsi_pm_type { #define DSI_BTA_TERM BIT(1) #define DSI_CMD_TERM BIT(0) +#define DSI_DATA_LANES_STOP_STATE 0xF +#define DSI_CLK_LANE_STOP_STATE BIT(4) + /* offsets for dynamic refresh */ #define DSI_DYNAMIC_REFRESH_CTRL 0x200 #define DSI_DYNAMIC_REFRESH_PIPE_DELAY 0x204 diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index 63b93f179116..4fc66c3c28c0 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -1940,7 +1940,7 @@ static int dsi_event_thread(void *data) struct mdss_dsi_ctrl_pdata *ctrl; unsigned long flag; struct sched_param param; - u32 todo = 0; + u32 todo = 0, ln_status; int ret; param.sched_priority = 16; @@ -1989,13 +1989,28 @@ static int dsi_event_thread(void *data) mdss_dsi_sw_reset(ctrl, true); if (todo & DSI_EV_DLNx_FIFO_OVERFLOW) { - pr_debug("%s: Handling overflow event\n", - __func__); mutex_lock(&dsi_mtx); - mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); - mdss_dsi_ctl_phy_reset(ctrl); - mdss_dsi_err_intr_ctrl(ctrl, DSI_INTR_ERROR_MASK, 1); - mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); + /* + * Run the overflow recovery sequence only when + * data lanes are in stop state and + * clock lane is not in Stop State. + */ + ln_status = MIPI_INP(ctrl->ctrl_base + 0x00a8); + pr_debug("%s: lane_status: 0x%x\n", + __func__, ln_status); + if (ctrl->recovery + && (ln_status + & DSI_DATA_LANES_STOP_STATE) + && !(ln_status + & DSI_CLK_LANE_STOP_STATE)) { + pr_debug("%s: Handling overflow event.\n", + __func__); + mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); + mdss_dsi_ctl_phy_reset(ctrl); + mdss_dsi_err_intr_ctrl(ctrl, + DSI_INTR_ERROR_MASK, 1); + mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); + } mutex_unlock(&dsi_mtx); }