diff options
| author | Padmanabhan Komanduru <pkomandu@codeaurora.org> | 2014-08-20 21:04:27 +0530 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:33:42 -0700 |
| commit | 7d8519628fd65576b7ea1705f3275a03d1ccc800 (patch) | |
| tree | 3bbf2c0ff29b25e2629d435d49d687cd6866c684 | |
| parent | 076e7000c9963dad8dd5aeb8fdde6efd3e71c03d (diff) | |
msm: mdss: add support for variable refresh rate for 8916/8939
Flush the MDP and DSI timing registers during variable refresh rate
operation for 8916/8939. Also, there is no need to wait for vsync
interrupt before programming the timing registers due to their
double buffer nature.
Change-Id: Ia349729069bd49f0c40ce41cccefdfb67cafe44c
Signed-off-by: Padmanabhan Komanduru <pkomandu@codeaurora.org>
[abhimany@codeaurora.org: minor confict resolution]
[abhimany@codeaurora.org: INIT_COMPLETION fixups]
Signed-off-by: Abhimanyu Kapur <abhimany@codeaurora.org>
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.c | 6 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 107 |
2 files changed, 94 insertions, 19 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index d30d4f3b9376..02642fa6e971 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -813,7 +813,7 @@ int mdss_dsi_cont_splash_on(struct mdss_panel_data *pdata) static void __mdss_dsi_update_video_mode_total(struct mdss_panel_data *pdata, int new_fps) { - u32 hsync_period, vsync_period; + u32 hsync_period, vsync_period, ctrl_rev; u32 new_dsi_v_total, current_dsi_v_total; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; @@ -849,6 +849,10 @@ static void __mdss_dsi_update_video_mode_total(struct mdss_panel_data *pdata, MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, (new_dsi_v_total & 0x7ffffff)); } + ctrl_rev = MIPI_INP(ctrl_pdata->ctrl_base); + /* Flush DSI TIMING registers for 8916/8939 */ + if (ctrl_rev == MDSS_DSI_HW_REV_103_1) + MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x1e4, 0x1); ctrl_pdata->panel_data.panel_info.mipi.frame_rate = new_fps; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index f09903d67a19..ac0f6ec3f508 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -600,6 +600,68 @@ static int mdss_mdp_video_vfp_fps_update(struct mdss_mdp_ctl *ctl, int new_fps) return 0; } +static int mdss_mdp_video_dfps_wait4vsync(struct mdss_mdp_ctl *ctl) +{ + int rc = 0; + struct mdss_mdp_video_ctx *ctx; + + ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data; + if (!ctx) { + pr_err("invalid ctx\n"); + return -ENODEV; + } + + video_vsync_irq_enable(ctl, true); + reinit_completion(&ctx->vsync_comp); + rc = wait_for_completion_timeout(&ctx->vsync_comp, + usecs_to_jiffies(VSYNC_TIMEOUT_US)); + WARN(rc <= 0, "timeout (%d) vsync interrupt on ctl=%d\n", + rc, ctl->num); + + video_vsync_irq_disable(ctl); + if (rc <= 0) + return -EPERM; + + return 0; +} + +static int mdss_mdp_video_dfps_check_line_cnt(struct mdss_mdp_ctl *ctl) +{ + struct mdss_panel_data *pdata; + u32 line_cnt; + pdata = ctl->panel_data; + if (pdata == NULL) { + pr_err("%s: Invalid panel data\n", __func__); + return -EINVAL; + } + + line_cnt = mdss_mdp_video_line_count(ctl); + if (line_cnt >= pdata->panel_info.yres/2) { + pr_err("Too few lines left line_cnt=%d yres/2=%d\n", + line_cnt, + pdata->panel_info.yres/2); + return -EPERM; + } + return 0; +} + +static void mdss_mdp_video_timegen_flush(struct mdss_mdp_ctl *ctl, + struct mdss_mdp_ctl *sctl) +{ + u32 ctl_flush, sctl_flush = 0; + ctl_flush = (BIT(31) >> (ctl->intf_num - MDSS_MDP_INTF0)); + if (sctl) { + sctl_flush = (BIT(31) >> (sctl->intf_num - MDSS_MDP_INTF0)); + if (ctl->split_flush_en) { + ctl_flush |= sctl_flush; + sctl_flush = 0; + } + } + mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl_flush); + if (sctl_flush) + mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_FLUSH, sctl_flush); +} + static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl, int new_fps) { @@ -607,6 +669,7 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, struct mdss_panel_data *pdata; int rc = 0; u32 hsync_period, vsync_period; + struct mdss_data_type *mdata; pr_debug("Updating fps for ctl=%d\n", ctl->num); @@ -622,6 +685,7 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, return -EINVAL; } + mdata = ctl->mdata; if (!pdata->panel_info.dynamic_fps) { pr_err("%s: Dynamic fps not enabled for this panel\n", __func__); @@ -646,36 +710,38 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, ctl->intf_num, rc); } else if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE) { - u32 line_cnt; + bool wait4vsync; unsigned long flags; if (!ctx->timegen_en) { pr_err("TG is OFF. DFPS mode invalid\n"); return -EINVAL; } - video_vsync_irq_enable(ctl, true); - reinit_completion(&ctx->vsync_comp); - rc = wait_for_completion_timeout(&ctx->vsync_comp, - usecs_to_jiffies(VSYNC_TIMEOUT_US)); - WARN(rc <= 0, "timeout (%d) vsync interrupt on ctl=%d\n", - rc, ctl->num); + /* + * MDP INTF registers are double buffered on + * 8916/8939. No need to wait for vsync for + * these targets. + */ + wait4vsync = (mdata->mdp_rev != MDSS_MDP_HW_REV_106) && + (mdata->mdp_rev != MDSS_MDP_HW_REV_108); - video_vsync_irq_disable(ctl); - /* Do not configure fps on vsync timeout */ - if (rc <= 0) - return rc; + if (wait4vsync) { + rc = mdss_mdp_video_dfps_wait4vsync(ctl); + if (rc < 0) { + pr_err("Error during wait4vsync\n"); + return rc; + } + } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); spin_lock_irqsave(&ctx->dfps_lock, flags); - line_cnt = mdss_mdp_video_line_count(ctl); - if (line_cnt >= pdata->panel_info.yres/2) { - pr_err("Too few lines left line_cnt=%d yres/2=%d", - line_cnt, - pdata->panel_info.yres/2); - rc = -EPERM; - goto exit_dfps; + if (wait4vsync) { + rc = mdss_mdp_video_dfps_check_line_cnt(ctl); + if (rc < 0) + goto exit_dfps; } + rc = mdss_mdp_video_vfp_fps_update(ctl, new_fps); if (rc < 0) { pr_err("%s: Error during DFPS\n", __func__); @@ -694,6 +760,11 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, (void *) (unsigned long) new_fps); WARN(rc, "intf %d panel fps update error (%d)\n", ctl->intf_num, rc); + + /* MDP INTF registers support DB on 8916/8939 */ + if (!wait4vsync) + mdss_mdp_video_timegen_flush(ctl, sctl); + exit_dfps: spin_unlock_irqrestore(&ctx->dfps_lock, flags); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); |
