From 9dda3223bc15bbf43babeae3fc704829af4a6e5f Mon Sep 17 00:00:00 2001 From: Vishnuvardhan Prodduturi Date: Fri, 20 Jan 2017 10:47:41 +0530 Subject: [PATCH 1/5] msm: mdss: add return values to MDSS recovery events When the target is in suspend or when shutdown is pending, the DSI recovery need not be taken care of. Add change to handle this case based on the return value of the MDSS recovery events. Change-Id: I5a5cd6743c15cca7ca42a40db7dcd552c95b20b6 Signed-off-by: Padmanabhan Komanduru Signed-off-by: Ashish Garg Signed-off-by: Vishnuvardhan Prodduturi --- drivers/video/fbdev/msm/mdss_dsi_host.c | 22 +++++++++++++++---- drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c | 20 +++++++++-------- drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 14 ++++++------ drivers/video/fbdev/msm/mdss_panel.h | 2 +- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index 734d3bee8fd0..8b28ee3f530f 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -766,6 +766,8 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl, u32 event) u32 data0, data1, mask = 0, data_lane_en = 0; struct mdss_dsi_ctrl_pdata *ctrl0, *ctrl1; u32 ln0, ln1, ln_ctrl0, ln_ctrl1, i; + int rc = 0; + /* * Add 2 ms delay suggested by HW team. * Check clk lane stop state after every 200 us @@ -787,9 +789,15 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl, u32 event) ctrl0 = mdss_dsi_get_ctrl_by_index(DSI_CTRL_0); ctrl1 = mdss_dsi_get_ctrl_by_index(DSI_CTRL_1); - if (ctrl0->recovery) - ctrl0->recovery->fxn(ctrl0->recovery->data, + if (ctrl0->recovery) { + rc = ctrl0->recovery->fxn(ctrl0->recovery->data, MDP_INTF_DSI_VIDEO_FIFO_OVERFLOW); + if (rc < 0) { + pr_debug("%s: Target is in suspend/shutdown\n", + __func__); + return; + } + } /* * Disable PHY contention detection and receive. * Configure the strength ctrl 1 register. @@ -879,9 +887,15 @@ static void mdss_dsi_ctl_phy_reset(struct mdss_dsi_ctrl_pdata *ctrl, u32 event) */ udelay(200); } else { - if (ctrl->recovery) - ctrl->recovery->fxn(ctrl->recovery->data, + if (ctrl->recovery) { + rc = ctrl->recovery->fxn(ctrl->recovery->data, MDP_INTF_DSI_VIDEO_FIFO_OVERFLOW); + if (rc < 0) { + pr_debug("%s: Target is in suspend/shutdown\n", + __func__); + return; + } + } /* Disable PHY contention detection and receive */ MIPI_OUTP((ctrl->phy_io.base) + 0x0188, 0); diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index dfd6226ce602..3c7d8fe99343 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -1197,7 +1197,7 @@ static int mdss_mdp_cmd_wait4readptr(struct mdss_mdp_cmd_ctx *ctx) return rc; } -static void mdss_mdp_cmd_intf_callback(void *data, int event) +static int mdss_mdp_cmd_intf_callback(void *data, int event) { struct mdss_mdp_cmd_ctx *ctx = data; struct mdss_mdp_pp_tear_check *te = NULL; @@ -1206,11 +1206,11 @@ static void mdss_mdp_cmd_intf_callback(void *data, int event) if (!data) { pr_err("%s: invalid ctx\n", __func__); - return; + return -EINVAL; } if (!ctx->ctl) - return; + return -EINVAL; switch (event) { case MDP_INTF_CALLBACK_DSI_WAIT: @@ -1222,7 +1222,7 @@ static void mdss_mdp_cmd_intf_callback(void *data, int event) * just return */ if (ctx->intf_stopped || !is_pingpong_split(ctx->ctl->mfd)) - return; + return -EINVAL; atomic_inc(&ctx->rdptr_cnt); /* enable clks and rd_ptr interrupt */ @@ -1231,7 +1231,7 @@ static void mdss_mdp_cmd_intf_callback(void *data, int event) mixer = mdss_mdp_mixer_get(ctx->ctl, MDSS_MDP_MIXER_MUX_LEFT); if (!mixer) { pr_err("%s: null mixer\n", __func__); - return; + return -EINVAL; } /* wait for read pointer */ @@ -1255,6 +1255,7 @@ static void mdss_mdp_cmd_intf_callback(void *data, int event) pr_debug("%s: unhandled event=%d\n", __func__, event); break; } + return 0; } static void mdss_mdp_cmd_lineptr_done(void *arg) @@ -1280,7 +1281,7 @@ static void mdss_mdp_cmd_lineptr_done(void *arg) spin_unlock(&ctx->clk_lock); } -static void mdss_mdp_cmd_intf_recovery(void *data, int event) +static int mdss_mdp_cmd_intf_recovery(void *data, int event) { struct mdss_mdp_cmd_ctx *ctx = data; unsigned long flags; @@ -1288,11 +1289,11 @@ static void mdss_mdp_cmd_intf_recovery(void *data, int event) if (!data) { pr_err("%s: invalid ctx\n", __func__); - return; + return -EINVAL; } if (!ctx->ctl) - return; + return -EINVAL; /* * Currently, only intf_fifo_underflow is @@ -1302,7 +1303,7 @@ static void mdss_mdp_cmd_intf_recovery(void *data, int event) if (event != MDP_INTF_DSI_CMD_FIFO_UNDERFLOW) { pr_warn("%s: unsupported recovery event:%d\n", __func__, event); - return; + return -EPERM; } if (atomic_read(&ctx->koff_cnt)) { @@ -1326,6 +1327,7 @@ static void mdss_mdp_cmd_intf_recovery(void *data, int event) if (notify_frame_timeout) mdss_mdp_ctl_notify(ctx->ctl, MDP_NOTIFY_FRAME_TIMEOUT); + return 0; } static void mdss_mdp_cmd_pingpong_done(void *arg) diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 5173567a3420..56192acb60b6 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -315,7 +315,7 @@ int mdss_mdp_video_addr_setup(struct mdss_data_type *mdata, return 0; } -static void mdss_mdp_video_intf_recovery(void *data, int event) +static int mdss_mdp_video_intf_recovery(void *data, int event) { struct mdss_mdp_video_ctx *ctx; struct mdss_mdp_ctl *ctl = data; @@ -327,7 +327,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event) if (!data) { pr_err("%s: invalid ctl\n", __func__); - return; + return -EINVAL; } /* @@ -338,7 +338,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event) if (event != MDP_INTF_DSI_VIDEO_FIFO_OVERFLOW) { pr_warn("%s: unsupported recovery event:%d\n", __func__, event); - return; + return -EPERM; } ctx = ctl->intf_ctx[MASTER_CTX]; @@ -353,7 +353,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event) clk_rate = DIV_ROUND_UP_ULL(clk_rate, 1000); /* in kHz */ if (!clk_rate) { pr_err("Unable to get proper clk_rate\n"); - return; + return -EINVAL; } /* * calculate clk_period as pico second to maintain good @@ -363,7 +363,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event) clk_period = DIV_ROUND_UP_ULL(1000000000, clk_rate); if (!clk_period) { pr_err("Unable to calculate clock period\n"); - return; + return -EINVAL; } min_ln_cnt = pinfo->lcdc.v_back_porch + pinfo->lcdc.v_pulse_width; active_lns_cnt = pinfo->yres; @@ -389,7 +389,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event) !ctx->timegen_en) { pr_warn("Target is in suspend or shutdown pending\n"); mutex_unlock(&ctl->offlock); - return; + return -EPERM; } line_cnt = mdss_mdp_video_line_count(ctl); @@ -399,7 +399,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event) pr_debug("%s, Needed lines left line_cnt=%d\n", __func__, line_cnt); mutex_unlock(&ctl->offlock); - return; + return 0; } else { pr_warn("line count is less. line_cnt = %d\n", line_cnt); diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index e466c0097540..c47ca2ddfe0b 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -195,7 +195,7 @@ enum { }; struct mdss_intf_recovery { - void (*fxn)(void *ctx, int event); + int (*fxn)(void *ctx, int event); void *data; }; From d1a2e03ebb9f3993d0e877bf536ffa902019a435 Mon Sep 17 00:00:00 2001 From: Vishnuvardhan Prodduturi Date: Fri, 20 Jan 2017 11:30:57 +0530 Subject: [PATCH 2/5] msm: mdss: clear BTA_DONE interrupt during DSI read operations In cases where DSI DMA done operation is performed but isr is not triggered due to CPU delays, we clear only the DMA_DONE interrupt. There is a possibility of a DSI read operation for DSI command mode panels where the DMA_DONE interrupt is cleared and DSI link clocks are turned off. After some time, the DSI isr gets triggered for BTA_DONE interrupt and since DSI link clocks are off, this causes an interrupt storm due to BTA_DONE interrupt not getting cleared. Clear the BTA_DONE interrupt as well for cases where DMA_DONE operation is done but isr not getting triggered. Change-Id: Iceb02e6dd78f4bbf313e2b4d252d6a30699619f0 Signed-off-by: Padmanabhan Komanduru Signed-off-by: Vishnuvardhan Prodduturi --- drivers/video/fbdev/msm/mdss_dsi_host.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index 8b28ee3f530f..d87e89d8901c 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -2148,8 +2148,8 @@ static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl, status = reg_val & DSI_INTR_CMD_DMA_DONE; if (status) { reg_val &= DSI_INTR_MASK_ALL; - /* clear CMD DMA isr only */ - reg_val |= DSI_INTR_CMD_DMA_DONE; + /* clear CMD DMA and BTA_DONE isr only */ + reg_val |= (DSI_INTR_CMD_DMA_DONE | DSI_INTR_BTA_DONE); MIPI_OUTP(ctrl->ctrl_base + 0x0110, reg_val); mdss_dsi_disable_irq_nosync(ctrl, DSI_CMD_TERM); complete(&ctrl->dma_comp); From 4072ee7757944a8fe36067bb9f7cd3d3fd0f794d Mon Sep 17 00:00:00 2001 From: Vishnuvardhan Prodduturi Date: Fri, 20 Jan 2017 11:39:58 +0530 Subject: [PATCH 3/5] msm: mdss: do not report overflow errors during read commands During a DSI DMA read command transaction, it is expected to have DSI FIFO overflow if the read operation duration exceeds one BLLP line time frame. Make sure not to trigger DSI FIFO overflow recovery sequence for such cases where DSI FIFO overflow error is masked. Change-Id: I0762a0f51d580a44cfa24ffac60cc465c241c733 Signed-off-by: Padmanabhan Komanduru Signed-off-by: Vishnuvardhan Prodduturi --- drivers/video/fbdev/msm/mdss_dsi_host.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index d87e89d8901c..98c5eda02f5b 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -3044,6 +3044,13 @@ static bool mdss_dsi_fifo_status(struct mdss_dsi_ctrl_pdata *ctrl) pr_err("%s: status=%x\n", __func__, status); + /* + * if DSI FIFO overflow is masked, + * do not report overflow error + */ + if (MIPI_INP(base + 0x10c) & 0xf0000) + status = status & 0xaaaaffff; + if (status & 0x44440000) {/* DLNx_HS_FIFO_OVERFLOW */ dsi_send_events(ctrl, DSI_EV_DLNx_FIFO_OVERFLOW, 0); /* Ignore FIFO EMPTY when overflow happens */ From eb973791c027c4e94df4730afef73196d880d879 Mon Sep 17 00:00:00 2001 From: Vishnuvardhan Prodduturi Date: Fri, 20 Jan 2017 17:40:40 +0530 Subject: [PATCH 4/5] msm: mdss: enable tearcheck while entering LP1 state In current implementation we disable tear check block when transitioning into ultra low power or power off state for doze mode. But it is not enabled back when moving from ultra low power state(LP2) to low power state(LP1), after which updates are expected. This change enables back tearcheck block when transitioning to LP1 from LP2 state. Change-Id: Ic0d8f97752ccf88470da2423f3f8d56a32de227f Signed-off-by: Sandeep Panda Signed-off-by: Vishnuvardhan Prodduturi --- drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index 3c7d8fe99343..714e1c06db78 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -3317,7 +3317,11 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state) ctx->intf_stopped = 0; if (sctx) sctx->intf_stopped = 0; - + /* + * Tearcheck was disabled while entering LP2 state. + * Enable it back to allow updates in LP1 state. + */ + mdss_mdp_tearcheck_enable(ctl, true); goto end; } } From 6ab42d60d15f6fd833fa194b198c3224b8ffeb0a Mon Sep 17 00:00:00 2001 From: Vishnuvardhan Prodduturi Date: Fri, 20 Jan 2017 22:21:02 +0530 Subject: [PATCH 5/5] msm: mdss: fix conditional check for panel LP configuration Add change to correct the conditional check for entering the panel in and out of LP configurations. Remove the unused enum structure related to panel blank status. Change-Id: Ic1140eafcc7cdd8d64c107bddc824eeca844462d Signed-off-by: Padmanabhan Komanduru Signed-off-by: Vishnuvardhan Prodduturi --- drivers/video/fbdev/msm/mdss_dsi.c | 9 +++++++-- drivers/video/fbdev/msm/mdss_dsi.h | 1 + drivers/video/fbdev/msm/mdss_panel.h | 6 ------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index c66d9f3b3a65..1cda3e2360dd 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -1559,10 +1559,12 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata) mdss_dsi_clk_ctrl(sctrl, sctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON); - if (mdss_dsi_is_panel_on_lp(pdata)) { + if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_LP) { pr_debug("%s: dsi_unblank with panel always on\n", __func__); if (ctrl_pdata->low_power_config) ret = ctrl_pdata->low_power_config(pdata, false); + if (!ret) + ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_LP; goto error; } @@ -1627,6 +1629,8 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state) pr_debug("%s: low power state requested\n", __func__); if (ctrl_pdata->low_power_config) ret = ctrl_pdata->low_power_config(pdata, true); + if (!ret) + ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_LP; goto error; } @@ -1669,7 +1673,8 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state) } ATRACE_END("dsi_panel_off"); } - ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_INIT; + ctrl_pdata->ctrl_state &= ~(CTRL_STATE_PANEL_INIT | + CTRL_STATE_PANEL_LP); } error: diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index df24352ff87d..bd9fd6c7d6c5 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -166,6 +166,7 @@ enum dsi_pm_type { #define CTRL_STATE_PANEL_INIT BIT(0) #define CTRL_STATE_MDP_ACTIVE BIT(1) #define CTRL_STATE_DSI_ACTIVE BIT(2) +#define CTRL_STATE_PANEL_LP BIT(3) #define DSI_NON_BURST_SYNCH_PULSE 0 #define DSI_NON_BURST_SYNCH_EVENT 1 diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index c47ca2ddfe0b..e75c4a3a7cc1 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -111,12 +111,6 @@ enum { MDSS_PANEL_POWER_LCD_DISABLED, }; -enum { - MDSS_PANEL_BLANK_BLANK = 0, - MDSS_PANEL_BLANK_UNBLANK, - MDSS_PANEL_BLANK_LOW_POWER, -}; - enum { MDSS_PANEL_LOW_PERSIST_MODE_OFF = 0, MDSS_PANEL_LOW_PERSIST_MODE_ON,