summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJayant Shekhar <jshekhar@codeaurora.org>2014-04-07 11:46:04 +0530
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:29:09 -0700
commit17f419e70900f74d37780f2e0343bd45afea1476 (patch)
treec20d006058495dff1dfccbcde6f99de182474048
parent7b23e8979ed1da489f311f658898f85f2135b223 (diff)
msm: mdss: Issue ctl sw reset when underrun happens
If underrun occurs in dual pipe mode (edp, or HDMI) then there is a chance the 3d_mux will get confused and route right to left and left to right. This will happen if it is on the right side when the underrun condition happens. To fix this following steps are required: - Disable HW recovery - When underrun is detected, wait for vsync. - Issue sw_reset to the ctl path. This is required to cleanly reset the 3d_mux in case the swap has occurred. Change-Id: I8fbf747da4720c12d48bc1ee431bab6224148e31 Signed-off-by: Jayant Shekhar <jshekhar@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c19
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c36
3 files changed, 58 insertions, 0 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index f4eca405cafe..04499b2d3845 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -186,6 +186,9 @@ struct mdss_mdp_ctl {
struct mdss_panel_data *panel_data;
struct mdss_mdp_vsync_handler vsync_handler;
+ struct mdss_mdp_vsync_handler recover_underrun_handler;
+ struct work_struct recover_work;
+ struct work_struct remove_underrun_handler;
struct mdss_mdp_img_rect roi;
struct mdss_mdp_img_rect roi_bkup;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
index ec533ecce44f..dba8e90043c9 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -468,6 +468,21 @@ static int mdss_mdp_video_wait4comp(struct mdss_mdp_ctl *ctl, void *arg)
return rc;
}
+static void recover_underrun_work(struct work_struct *work)
+{
+ struct mdss_mdp_ctl *ctl =
+ container_of(work, typeof(*ctl), recover_work);
+
+ if (!ctl || !ctl->add_vsync_handler) {
+ pr_err("ctl or vsync handler is NULL\n");
+ return;
+ }
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ ctl->add_vsync_handler(ctl, &ctl->recover_underrun_handler);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+}
+
static void mdss_mdp_video_underrun_intr_done(void *arg)
{
struct mdss_mdp_ctl *ctl = arg;
@@ -479,6 +494,9 @@ static void mdss_mdp_video_underrun_intr_done(void *arg)
MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0", "dsi1", "edp", "hdmi", "panic");
pr_debug("display underrun detected for ctl=%d count=%d\n", ctl->num,
ctl->underrun_cnt);
+
+ if (ctl->opmode & MDSS_MDP_CTL_OP_PACK_3D_ENABLE)
+ schedule_work(&ctl->recover_work);
}
static int mdss_mdp_video_vfp_fps_update(struct mdss_mdp_ctl *ctl, int new_fps)
@@ -804,6 +822,7 @@ int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl)
spin_lock_init(&ctx->vsync_lock);
mutex_init(&ctx->vsync_mtx);
atomic_set(&ctx->vsync_ref, 0);
+ INIT_WORK(&ctl->recover_work, recover_underrun_work);
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
mdss_mdp_video_vsync_intr_done, ctl);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 181ebc0abc43..c69ca87fd3d0 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -1873,6 +1873,35 @@ pan_display_error:
mutex_unlock(&mdp5_data->ov_lock);
}
+static void remove_underrun_vsync_handler(struct work_struct *work)
+{
+ int rc;
+ struct mdss_mdp_ctl *ctl =
+ container_of(work, typeof(*ctl), remove_underrun_handler);
+
+ if (!ctl || !ctl->remove_vsync_handler) {
+ pr_err("ctl or vsync handler is NULL\n");
+ return;
+ }
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ rc = ctl->remove_vsync_handler(ctl,
+ &ctl->recover_underrun_handler);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+}
+
+static void mdss_mdp_recover_underrun_handler(struct mdss_mdp_ctl *ctl,
+ ktime_t t)
+{
+ if (!ctl) {
+ pr_err("ctl is NULL\n");
+ return;
+ }
+
+ mdss_mdp_ctl_reset(ctl);
+ schedule_work(&ctl->remove_underrun_handler);
+}
+
/* function is called in irq context should have minimum processing */
static void mdss_mdp_overlay_handle_vsync(struct mdss_mdp_ctl *ctl,
ktime_t t)
@@ -3041,6 +3070,13 @@ static struct mdss_mdp_ctl *__mdss_mdp_overlay_ctl_init(
mdss_mdp_overlay_handle_vsync;
ctl->vsync_handler.cmd_post_flush = false;
+ ctl->recover_underrun_handler.vsync_handler =
+ mdss_mdp_recover_underrun_handler;
+ ctl->recover_underrun_handler.cmd_post_flush = false;
+
+ INIT_WORK(&ctl->remove_underrun_handler,
+ remove_underrun_vsync_handler);
+
if (mfd->split_display && pdata->next) {
/* enable split display */
rc = mdss_mdp_ctl_split_display_setup(ctl, pdata->next);