diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_host.c | 25 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 60 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_panel.h | 1 |
3 files changed, 84 insertions, 2 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index 98c5eda02f5b..982e7a02ffa3 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -41,6 +41,8 @@ #define LANE_SWAP_CTRL 0x0B0 #define LOGICAL_LANE_SWAP_CTRL 0x310 +#define MAX_BTA_WAIT_RETRY 5 + #define CEIL(x, y) (((x) + ((y)-1)) / (y)) struct mdss_dsi_ctrl_pdata *ctrl_list[DSI_CTRL_MAX]; @@ -1451,8 +1453,7 @@ static int mdss_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl) if (ctrl->ctrl_state & CTRL_STATE_MDP_ACTIVE) { mdss_dsi_wait4video_done(ctrl); v_total = mdss_panel_get_vtotal(pinfo); - v_blank = pinfo->lcdc.v_back_porch + pinfo->lcdc.v_front_porch + - pinfo->lcdc.v_pulse_width; + v_blank = pinfo->lcdc.v_back_porch + pinfo->lcdc.v_pulse_width; if (pinfo->dynamic_fps && pinfo->current_fps) fps = pinfo->current_fps; else @@ -1483,6 +1484,8 @@ int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata) int ret = 0; unsigned long flag; int ignore_underflow = 0; + int retry_count = 0; + int in_blanking = 0; if (ctrl_pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); @@ -1508,7 +1511,25 @@ int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata) reinit_completion(&ctrl_pdata->bta_comp); mdss_dsi_enable_irq(ctrl_pdata, DSI_BTA_TERM); spin_unlock_irqrestore(&ctrl_pdata->mdp_lock, flag); +wait: mdss_dsi_wait4video_eng_busy(ctrl_pdata); + if (ctrl_pdata->panel_mode == DSI_VIDEO_MODE) { + in_blanking = ctrl_pdata->mdp_callback->fxn( + ctrl_pdata->mdp_callback->data, + MDP_INTF_CALLBACK_CHECK_LINE_COUNT); + /* Try for maximum of 5 attempts */ + if (in_blanking && (retry_count < MAX_BTA_WAIT_RETRY)) { + pr_debug("%s: not in active region\n", __func__); + retry_count++; + goto wait; + } + } + if (retry_count == MAX_BTA_WAIT_RETRY) + MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl", + "dsi0_phy", "dsi1_ctrl", "dsi1_phy", + "vbif", "vbif_nrt", "dbg_bus", + "vbif_dbg_bus", "panic"); + /* mask out overflow errors */ if (ignore_underflow) mdss_dsi_set_reg(ctrl_pdata, 0x10c, 0x0f0000, 0x0f0000); diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 67cbf076b8ac..7537ca13d2c0 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -83,6 +83,7 @@ struct mdss_mdp_video_ctx { struct mutex vsync_mtx; struct list_head vsync_handlers; struct mdss_intf_recovery intf_recovery; + struct mdss_intf_recovery intf_mdp_callback; struct work_struct early_wakeup_dfps_work; atomic_t lineptr_ref; @@ -1896,6 +1897,58 @@ static void mdss_mdp_handoff_programmable_fetch(struct mdss_mdp_ctl *ctl, } } +static int mdss_mdp_video_intf_callback(void *data, int event) +{ + struct mdss_mdp_video_ctx *ctx; + struct mdss_mdp_ctl *ctl = data; + struct mdss_panel_info *pinfo; + u32 line_cnt, min_ln_cnt, active_lns_cnt, line_buff = 50; + + if (!data) { + pr_err("%s: invalid ctl\n", __func__); + return -EINVAL; + } + + ctx = ctl->intf_ctx[MASTER_CTX]; + pr_debug("%s: ctl num = %d, event = %d\n", + __func__, ctl->num, event); + + if (!ctl->is_video_mode) + return 0; + + pinfo = &ctl->panel_data->panel_info; + min_ln_cnt = pinfo->lcdc.v_back_porch + pinfo->lcdc.v_pulse_width; + active_lns_cnt = pinfo->yres; + + switch (event) { + case MDP_INTF_CALLBACK_CHECK_LINE_COUNT: + if (!ctl || !ctx || !ctx->timegen_en) { + pr_debug("%s: no need to check for active line\n", + __func__); + goto end; + } + + line_cnt = mdss_mdp_video_line_count(ctl); + + if ((line_cnt >= min_ln_cnt) && (line_cnt < + (min_ln_cnt + active_lns_cnt - line_buff))) { + pr_debug("%s: line count is within active range=%d\n", + __func__, line_cnt); + goto end; + } else { + pr_debug("line count is less. line_cnt = %d\n", + line_cnt); + return -EPERM; + } + break; + default: + pr_debug("%s: unhandled event!\n", __func__); + break; + } +end: + return 0; +} + static int mdss_mdp_video_ctx_setup(struct mdss_mdp_ctl *ctl, struct mdss_mdp_video_ctx *ctx, struct mdss_panel_info *pinfo) { @@ -1929,6 +1982,13 @@ static int mdss_mdp_video_ctx_setup(struct mdss_mdp_ctl *ctl, pr_err("Failed to register intf recovery handler\n"); return -EINVAL; } + + ctx->intf_mdp_callback.fxn = mdss_mdp_video_intf_callback; + ctx->intf_mdp_callback.data = ctl; + mdss_mdp_ctl_intf_event(ctl, + MDSS_EVENT_REGISTER_MDP_CALLBACK, + (void *)&ctx->intf_mdp_callback, + CTL_INTF_EVENT_FLAG_DEFAULT); } else { ctx->intf_recovery.fxn = NULL; ctx->intf_recovery.data = NULL; diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index e75c4a3a7cc1..d5de8807f7a6 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -186,6 +186,7 @@ struct mdss_panel_cfg { enum { MDP_INTF_CALLBACK_DSI_WAIT, + MDP_INTF_CALLBACK_CHECK_LINE_COUNT, }; struct mdss_intf_recovery { |
