summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c25
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c60
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h1
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 {