Loading drivers/video/msm/mdss/mdss_dsi.h +10 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ enum dsi_pm_type { #define DSI_CMD_DST_FORMAT_RGB666 7 #define DSI_CMD_DST_FORMAT_RGB888 8 #define DSI_INTR_DESJEW_MASK BIT(31) #define DSI_INTR_DYNAMIC_REFRESH_MASK BIT(29) #define DSI_INTR_DYNAMIC_REFRESH_DONE BIT(28) #define DSI_INTR_ERROR_MASK BIT(25) Loading @@ -166,6 +167,15 @@ enum dsi_pm_type { /* Update this if more interrupt masks are added in future chipsets */ #define DSI_INTR_TOTAL_MASK 0x2222AA02 #define DSI_INTR_MASK_ALL \ (DSI_INTR_DESJEW_MASK | \ DSI_INTR_DYNAMIC_REFRESH_MASK | \ DSI_INTR_ERROR_MASK | \ DSI_INTR_BTA_DONE_MASK | \ DSI_INTR_VIDEO_DONE_MASK | \ DSI_INTR_CMD_MDP_DONE_MASK | \ DSI_INTR_CMD_DMA_DONE_MASK) #define DSI_CMD_TRIGGER_NONE 0x0 /* mdp trigger */ #define DSI_CMD_TRIGGER_TE 0x02 #define DSI_CMD_TRIGGER_SW 0x04 Loading drivers/video/msm/mdss/mdss_dsi_host.c +69 −30 Original line number Diff line number Diff line Loading @@ -510,6 +510,9 @@ static void mdss_dsi_wait_clk_lane_to_stop(struct mdss_dsi_ctrl_pdata *ctrl) /* clear clk lane tx stop -- bit 20 */ mdss_dsi_cfg_lane_ctrl(ctrl, BIT(20), 0); } static void mdss_dsi_stop_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl); /* * mdss_dsi_start_hs_clk_lane: * this function is work around solution for 8994 dsi clk lane Loading @@ -517,6 +520,10 @@ static void mdss_dsi_wait_clk_lane_to_stop(struct mdss_dsi_ctrl_pdata *ctrl) */ static void mdss_dsi_start_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl) { /* make sure clk lane is stopped */ mdss_dsi_stop_hs_clk_lane(ctrl); mutex_lock(&ctrl->clk_lane_mutex); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); if (ctrl->clk_lane_cnt) { Loading @@ -539,21 +546,16 @@ static void mdss_dsi_start_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl) * this function is work around solution for 8994 dsi clk lane * may stuck at HS problem */ static void mdss_dsi_stop_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl, u32 term) static void mdss_dsi_stop_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl) { u32 fifo = 0; u32 lane = 0; unsigned long flags; mutex_lock(&ctrl->clk_lane_mutex); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); if (ctrl->clk_lane_cnt != 1) { pr_err("%s: ndx=%d wait had been done, cnt=%d\n", __func__, ctrl->ndx, ctrl->clk_lane_cnt); if (ctrl->clk_lane_cnt == 0) /* stopped already */ goto release; } mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); /* fifo */ if (readl_poll_timeout(((ctrl->ctrl_base) + 0x000c), fifo, Loading @@ -572,7 +574,6 @@ static void mdss_dsi_stop_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl, pr_err("%s: datalane NOT stopped, lane=%x\n", __func__, lane); } end: /* stop force clk lane hs */ mdss_dsi_cfg_lane_ctrl(ctrl, BIT(28), 0); Loading @@ -580,18 +581,11 @@ end: mdss_dsi_wait_clk_lane_to_stop(ctrl); ctrl->clk_lane_cnt = 0; mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); release: if (term == DSI_MDP_TERM) { spin_lock_irqsave(&ctrl->mdp_lock, flags); ctrl->mdp_busy = false; complete_all(&ctrl->mdp_comp); spin_unlock_irqrestore(&ctrl->mdp_lock, flags); } pr_debug("%s: ndx=%d, cnt=%d\n", __func__, ctrl->ndx, ctrl->clk_lane_cnt); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); mutex_unlock(&ctrl->clk_lane_mutex); } Loading Loading @@ -621,10 +615,10 @@ static void mdss_dsi_cmd_stop_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl) mctrl = mdss_dsi_get_other_ctrl(ctrl); if (mctrl) mdss_dsi_stop_hs_clk_lane(mctrl, DSI_CMD_TERM); mdss_dsi_stop_hs_clk_lane(mctrl); } mdss_dsi_stop_hs_clk_lane(ctrl, DSI_CMD_TERM); mdss_dsi_stop_hs_clk_lane(ctrl); } static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl) Loading Loading @@ -2000,6 +1994,50 @@ void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl) spin_unlock_irqrestore(&ctrl->mdp_lock, flag); } static int mdss_dsi_mdp_busy_tout_check(struct mdss_dsi_ctrl_pdata *ctrl) { unsigned long flag; u32 isr; bool stop_hs_clk = false; int tout = 1; /* * two possible scenario: * 1) DSI_INTR_CMD_MDP_DONE set but isr not fired * 2) DSI_INTR_CMD_MDP_DONE set and cleared (isr fired) * but event_thread not wakeup */ mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); spin_lock_irqsave(&ctrl->mdp_lock, flag); isr = MIPI_INP(ctrl->ctrl_base + 0x0110); if (isr & DSI_INTR_CMD_MDP_DONE) { WARN(1, "INTR_CMD_MDP_DONE set but isr not fired\n"); isr &= DSI_INTR_MASK_ALL; isr |= DSI_INTR_CMD_MDP_DONE; /* clear this isr only */ MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr); mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM); ctrl->mdp_busy = false; if (ctrl->cmd_clk_ln_recovery_en && ctrl->panel_mode == DSI_CMD_MODE) { /* has hs_lane_recovery do the work */ stop_hs_clk = true; } tout = 0; /* recovered */ } spin_unlock_irqrestore(&ctrl->mdp_lock, flag); if (stop_hs_clk) mdss_dsi_stop_hs_clk_lane(ctrl); complete_all(&ctrl->mdp_comp); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); return tout; } void mdss_dsi_cmd_mdp_busy(struct mdss_dsi_ctrl_pdata *ctrl) { unsigned long flags; Loading @@ -2024,9 +2062,11 @@ void mdss_dsi_cmd_mdp_busy(struct mdss_dsi_ctrl_pdata *ctrl) rc = 1; spin_unlock_irqrestore(&ctrl->mdp_lock, flags); if (!rc) { if (mdss_dsi_mdp_busy_tout_check(ctrl)) { pr_err("%s: timeout error\n", __func__); MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl", "dsi0_phy", "dsi1_ctrl", "dsi1_phy", "panic"); MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl", "dsi0_phy", "dsi1_ctrl", "dsi1_phy", "panic"); } } } Loading Loading @@ -2125,10 +2165,8 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) /* * when partial update enabled, the roi of pinfo * is updated before mdp kickoff. Either width or * height of roi is 0, then it is false kickoff so * no mdp_busy flag set needed. * when partial update disabled, mdp_busy flag * alway set. * height of roi is non zero, then really kickoff * will followed. */ if (!roi || (roi->w != 0 || roi->h != 0)) { if (ctrl->cmd_clk_ln_recovery_en && Loading Loading @@ -2348,7 +2386,7 @@ static int dsi_event_thread(void *data) } if (todo & DSI_EV_STOP_HS_CLK_LANE) mdss_dsi_stop_hs_clk_lane(ctrl, arg); mdss_dsi_stop_hs_clk_lane(ctrl); } return 0; Loading Loading @@ -2557,12 +2595,13 @@ irqreturn_t mdss_dsi_isr(int irq, void *ptr) mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM); if (ctrl->cmd_clk_ln_recovery_en && ctrl->panel_mode == DSI_CMD_MODE) { /* stop force clk lane hs */ mdss_dsi_cfg_lane_ctrl(ctrl, BIT(28), 0); dsi_send_events(ctrl, DSI_EV_STOP_HS_CLK_LANE, DSI_MDP_TERM); } else { } ctrl->mdp_busy = false; complete_all(&ctrl->mdp_comp); } spin_unlock(&ctrl->mdp_lock); } Loading Loading
drivers/video/msm/mdss/mdss_dsi.h +10 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ enum dsi_pm_type { #define DSI_CMD_DST_FORMAT_RGB666 7 #define DSI_CMD_DST_FORMAT_RGB888 8 #define DSI_INTR_DESJEW_MASK BIT(31) #define DSI_INTR_DYNAMIC_REFRESH_MASK BIT(29) #define DSI_INTR_DYNAMIC_REFRESH_DONE BIT(28) #define DSI_INTR_ERROR_MASK BIT(25) Loading @@ -166,6 +167,15 @@ enum dsi_pm_type { /* Update this if more interrupt masks are added in future chipsets */ #define DSI_INTR_TOTAL_MASK 0x2222AA02 #define DSI_INTR_MASK_ALL \ (DSI_INTR_DESJEW_MASK | \ DSI_INTR_DYNAMIC_REFRESH_MASK | \ DSI_INTR_ERROR_MASK | \ DSI_INTR_BTA_DONE_MASK | \ DSI_INTR_VIDEO_DONE_MASK | \ DSI_INTR_CMD_MDP_DONE_MASK | \ DSI_INTR_CMD_DMA_DONE_MASK) #define DSI_CMD_TRIGGER_NONE 0x0 /* mdp trigger */ #define DSI_CMD_TRIGGER_TE 0x02 #define DSI_CMD_TRIGGER_SW 0x04 Loading
drivers/video/msm/mdss/mdss_dsi_host.c +69 −30 Original line number Diff line number Diff line Loading @@ -510,6 +510,9 @@ static void mdss_dsi_wait_clk_lane_to_stop(struct mdss_dsi_ctrl_pdata *ctrl) /* clear clk lane tx stop -- bit 20 */ mdss_dsi_cfg_lane_ctrl(ctrl, BIT(20), 0); } static void mdss_dsi_stop_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl); /* * mdss_dsi_start_hs_clk_lane: * this function is work around solution for 8994 dsi clk lane Loading @@ -517,6 +520,10 @@ static void mdss_dsi_wait_clk_lane_to_stop(struct mdss_dsi_ctrl_pdata *ctrl) */ static void mdss_dsi_start_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl) { /* make sure clk lane is stopped */ mdss_dsi_stop_hs_clk_lane(ctrl); mutex_lock(&ctrl->clk_lane_mutex); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); if (ctrl->clk_lane_cnt) { Loading @@ -539,21 +546,16 @@ static void mdss_dsi_start_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl) * this function is work around solution for 8994 dsi clk lane * may stuck at HS problem */ static void mdss_dsi_stop_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl, u32 term) static void mdss_dsi_stop_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl) { u32 fifo = 0; u32 lane = 0; unsigned long flags; mutex_lock(&ctrl->clk_lane_mutex); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); if (ctrl->clk_lane_cnt != 1) { pr_err("%s: ndx=%d wait had been done, cnt=%d\n", __func__, ctrl->ndx, ctrl->clk_lane_cnt); if (ctrl->clk_lane_cnt == 0) /* stopped already */ goto release; } mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); /* fifo */ if (readl_poll_timeout(((ctrl->ctrl_base) + 0x000c), fifo, Loading @@ -572,7 +574,6 @@ static void mdss_dsi_stop_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl, pr_err("%s: datalane NOT stopped, lane=%x\n", __func__, lane); } end: /* stop force clk lane hs */ mdss_dsi_cfg_lane_ctrl(ctrl, BIT(28), 0); Loading @@ -580,18 +581,11 @@ end: mdss_dsi_wait_clk_lane_to_stop(ctrl); ctrl->clk_lane_cnt = 0; mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); release: if (term == DSI_MDP_TERM) { spin_lock_irqsave(&ctrl->mdp_lock, flags); ctrl->mdp_busy = false; complete_all(&ctrl->mdp_comp); spin_unlock_irqrestore(&ctrl->mdp_lock, flags); } pr_debug("%s: ndx=%d, cnt=%d\n", __func__, ctrl->ndx, ctrl->clk_lane_cnt); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); mutex_unlock(&ctrl->clk_lane_mutex); } Loading Loading @@ -621,10 +615,10 @@ static void mdss_dsi_cmd_stop_hs_clk_lane(struct mdss_dsi_ctrl_pdata *ctrl) mctrl = mdss_dsi_get_other_ctrl(ctrl); if (mctrl) mdss_dsi_stop_hs_clk_lane(mctrl, DSI_CMD_TERM); mdss_dsi_stop_hs_clk_lane(mctrl); } mdss_dsi_stop_hs_clk_lane(ctrl, DSI_CMD_TERM); mdss_dsi_stop_hs_clk_lane(ctrl); } static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl) Loading Loading @@ -2000,6 +1994,50 @@ void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl) spin_unlock_irqrestore(&ctrl->mdp_lock, flag); } static int mdss_dsi_mdp_busy_tout_check(struct mdss_dsi_ctrl_pdata *ctrl) { unsigned long flag; u32 isr; bool stop_hs_clk = false; int tout = 1; /* * two possible scenario: * 1) DSI_INTR_CMD_MDP_DONE set but isr not fired * 2) DSI_INTR_CMD_MDP_DONE set and cleared (isr fired) * but event_thread not wakeup */ mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); spin_lock_irqsave(&ctrl->mdp_lock, flag); isr = MIPI_INP(ctrl->ctrl_base + 0x0110); if (isr & DSI_INTR_CMD_MDP_DONE) { WARN(1, "INTR_CMD_MDP_DONE set but isr not fired\n"); isr &= DSI_INTR_MASK_ALL; isr |= DSI_INTR_CMD_MDP_DONE; /* clear this isr only */ MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr); mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM); ctrl->mdp_busy = false; if (ctrl->cmd_clk_ln_recovery_en && ctrl->panel_mode == DSI_CMD_MODE) { /* has hs_lane_recovery do the work */ stop_hs_clk = true; } tout = 0; /* recovered */ } spin_unlock_irqrestore(&ctrl->mdp_lock, flag); if (stop_hs_clk) mdss_dsi_stop_hs_clk_lane(ctrl); complete_all(&ctrl->mdp_comp); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); return tout; } void mdss_dsi_cmd_mdp_busy(struct mdss_dsi_ctrl_pdata *ctrl) { unsigned long flags; Loading @@ -2024,9 +2062,11 @@ void mdss_dsi_cmd_mdp_busy(struct mdss_dsi_ctrl_pdata *ctrl) rc = 1; spin_unlock_irqrestore(&ctrl->mdp_lock, flags); if (!rc) { if (mdss_dsi_mdp_busy_tout_check(ctrl)) { pr_err("%s: timeout error\n", __func__); MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl", "dsi0_phy", "dsi1_ctrl", "dsi1_phy", "panic"); MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl", "dsi0_phy", "dsi1_ctrl", "dsi1_phy", "panic"); } } } Loading Loading @@ -2125,10 +2165,8 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) /* * when partial update enabled, the roi of pinfo * is updated before mdp kickoff. Either width or * height of roi is 0, then it is false kickoff so * no mdp_busy flag set needed. * when partial update disabled, mdp_busy flag * alway set. * height of roi is non zero, then really kickoff * will followed. */ if (!roi || (roi->w != 0 || roi->h != 0)) { if (ctrl->cmd_clk_ln_recovery_en && Loading Loading @@ -2348,7 +2386,7 @@ static int dsi_event_thread(void *data) } if (todo & DSI_EV_STOP_HS_CLK_LANE) mdss_dsi_stop_hs_clk_lane(ctrl, arg); mdss_dsi_stop_hs_clk_lane(ctrl); } return 0; Loading Loading @@ -2557,12 +2595,13 @@ irqreturn_t mdss_dsi_isr(int irq, void *ptr) mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM); if (ctrl->cmd_clk_ln_recovery_en && ctrl->panel_mode == DSI_CMD_MODE) { /* stop force clk lane hs */ mdss_dsi_cfg_lane_ctrl(ctrl, BIT(28), 0); dsi_send_events(ctrl, DSI_EV_STOP_HS_CLK_LANE, DSI_MDP_TERM); } else { } ctrl->mdp_busy = false; complete_all(&ctrl->mdp_comp); } spin_unlock(&ctrl->mdp_lock); } Loading