diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 3 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 19 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_overlay.c | 36 |
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); |
