diff options
| author | Ajay Singh Parmar <aparmar@codeaurora.org> | 2016-03-25 23:15:10 -0700 |
|---|---|---|
| committer | Kyle Yan <kyan@codeaurora.org> | 2016-04-28 16:45:26 -0700 |
| commit | 50d6b2a04e6987dcc8e3d0240af912c159365227 (patch) | |
| tree | 413591035c82a50adf6bf9700fd72f4dca810b9d /drivers/video/fbdev | |
| parent | 6fae8899dc8c34668ad35d6a8161e4480474e455 (diff) | |
msm: mdss: add multi-mode support for dynamic fps
In some cases, updating fps need both porch and clock
update. Add support to update both porch and clock settings
for a given resolution to attain required fps.
Change-Id: I8c75ef09121c2d20e04380ead2b805c7b114acad
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_ctl.c | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 14 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_overlay.c | 59 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_panel.h | 27 |
5 files changed, 83 insertions, 21 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index b47c784f1582..30b2e4be940c 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -1400,7 +1400,7 @@ int mdss_mdp_secure_display_ctrl(unsigned int enable); int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd); int mdss_mdp_dfps_update_params(struct msm_fb_data_type *mfd, - struct mdss_panel_data *pdata, int dfps); + struct mdss_panel_data *pdata, struct dynamic_fps_data *data); int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd, struct file *file, struct mdp_layer_commit_v1 *ov_commit); int mdss_mdp_layer_pre_commit(struct msm_fb_data_type *mfd, diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 908807104770..f0f855efc290 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -5074,6 +5074,8 @@ int mdss_mdp_ctl_update_fps(struct mdss_mdp_ctl *ctl) if ((pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) || (pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP) || + (pinfo->dfps_update == + DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) || pinfo->dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { new_fps = mdss_panel_get_framerate(pinfo); } else { diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 6924e6499ac5..9eae668526e4 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -827,10 +827,10 @@ static int mdss_mdp_video_fps_update(struct mdss_mdp_video_ctx *ctx, int rc; if (pdata->panel_info.dfps_update == - DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP) - rc = mdss_mdp_video_hfp_fps_update(ctx, pdata); - else + DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) rc = mdss_mdp_video_vfp_fps_update(ctx, pdata); + else + rc = mdss_mdp_video_hfp_fps_update(ctx, pdata); return rc; } @@ -985,7 +985,9 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, int new_fps) } else if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP || pdata->panel_info.dfps_update - == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP) { + == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP || + pdata->panel_info.dfps_update + == DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) { unsigned long flags; if (!ctx->timegen_en) { pr_err("TG is OFF. DFPS mode invalid\n"); @@ -1644,6 +1646,7 @@ static void early_wakeup_dfps_update_work(struct work_struct *work) struct mdss_panel_info *pinfo; struct msm_fb_data_type *mfd; struct mdss_mdp_ctl *ctl; + struct dynamic_fps_data data = {0}; int ret = 0; int dfps; @@ -1680,7 +1683,8 @@ static void early_wakeup_dfps_update_work(struct work_struct *work) goto exit; } - if (mdss_mdp_dfps_update_params(mfd, pdata, dfps)) + data.fps = dfps; + if (mdss_mdp_dfps_update_params(mfd, pdata, &data)) pr_err("failed to set dfps params!\n"); /* update the HW with the new fps */ diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index dafd9f203ab0..e44232be6e56 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -2768,7 +2768,9 @@ static void cache_initial_timings(struct mdss_panel_data *pdata) pdata->panel_info.lcdc.v_front_porch; } else if (pdata->panel_info.dfps_update == - DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP) { + DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP || + pdata->panel_info.dfps_update == + DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) { pdata->panel_info.saved_total = mdss_panel_get_htotal(&pdata->panel_info, true); pdata->panel_info.saved_fporch = @@ -2786,8 +2788,10 @@ static inline void dfps_update_fps(struct mdss_panel_info *pinfo, u32 fps) } static void dfps_update_panel_params(struct mdss_panel_data *pdata, - u32 new_fps) + struct dynamic_fps_data *data) { + u32 new_fps = data->fps; + /* Keep initial values before any dfps update */ cache_initial_timings(pdata); @@ -2823,7 +2827,20 @@ static void dfps_update_panel_params(struct mdss_panel_data *pdata, pdata->panel_info.saved_fporch - add_h_pixels; dfps_update_fps(&pdata->panel_info, new_fps); + } else if (pdata->panel_info.dfps_update == + DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) { + + pr_debug("hfp=%d, hbp=%d, hpw=%d, clk=%d, fps=%d\n", + data->hfp, data->hbp, data->hpw, + data->clk_rate, data->fps); + + pdata->panel_info.lcdc.h_front_porch = data->hfp; + pdata->panel_info.lcdc.h_back_porch = data->hbp; + pdata->panel_info.lcdc.h_pulse_width = data->hpw; + + pdata->panel_info.clk_rate = data->clk_rate; + dfps_update_fps(&pdata->panel_info, new_fps); } else { dfps_update_fps(&pdata->panel_info, new_fps); mdss_panel_update_clk_rate(&pdata->panel_info, new_fps); @@ -2831,10 +2848,11 @@ static void dfps_update_panel_params(struct mdss_panel_data *pdata, } int mdss_mdp_dfps_update_params(struct msm_fb_data_type *mfd, - struct mdss_panel_data *pdata, int dfps) + struct mdss_panel_data *pdata, struct dynamic_fps_data *dfps_data) { struct fb_var_screeninfo *var = &mfd->fbi->var; struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); + u32 dfps = dfps_data->fps; mutex_lock(&mdp5_data->dfps_lock); @@ -2851,9 +2869,9 @@ int mdss_mdp_dfps_update_params(struct msm_fb_data_type *mfd, dfps = pdata->panel_info.max_fps; } - dfps_update_panel_params(pdata, dfps); + dfps_update_panel_params(pdata, dfps_data); if (pdata->next) - dfps_update_panel_params(pdata->next, dfps); + dfps_update_panel_params(pdata->next, dfps_data); /* * Update the panel info in the upstream @@ -2872,17 +2890,12 @@ int mdss_mdp_dfps_update_params(struct msm_fb_data_type *mfd, static ssize_t dynamic_fps_sysfs_wta_dfps(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int dfps, panel_fps, rc = 0; + int panel_fps, rc = 0; struct mdss_panel_data *pdata; struct fb_info *fbi = dev_get_drvdata(dev); struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); - - rc = kstrtoint(buf, 10, &dfps); - if (rc) { - pr_err("%s: kstrtoint failed. rc=%d\n", __func__, rc); - return rc; - } + struct dynamic_fps_data data = {0}; if (!mdp5_data->ctl || !mdss_mdp_ctl_is_power_on(mdp5_data->ctl)) { pr_debug("panel is off\n"); @@ -2901,15 +2914,31 @@ static ssize_t dynamic_fps_sysfs_wta_dfps(struct device *dev, return -EINVAL; } + if (pdata->panel_info.dfps_update == + DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) { + if (sscanf(buf, "%d %d %d %d %d", + &data.hfp, &data.hbp, &data.hpw, + &data.clk_rate, &data.fps) != 5) { + pr_err("could not read input\n"); + return -EINVAL; + } + } else { + rc = kstrtoint(buf, 10, &data.fps); + if (rc) { + pr_err("%s: kstrtoint failed. rc=%d\n", __func__, rc); + return rc; + } + } + panel_fps = mdss_panel_get_framerate(&pdata->panel_info); - if (dfps == panel_fps) { + if (data.fps == panel_fps) { pr_debug("%s: FPS is already %d\n", - __func__, dfps); + __func__, data.fps); return count; } - rc = mdss_mdp_dfps_update_params(mfd, pdata, dfps); + rc = mdss_mdp_dfps_update_params(mfd, pdata, &data); if (rc) { pr_err("failed to set dfps params\n"); return rc; diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 12945edd93e8..7528f642149b 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -416,11 +416,38 @@ struct edp_panel_info { char frame_rate; /* fps */ }; +/** + * struct dynamic_fps_data - defines dynamic fps related data + * @hfp: horizontal front porch + * @hbp: horizontal back porch + * @hpw: horizontal pulse width + * @clk_rate: panel clock rate in HZ + * @fps: frames per second + */ +struct dynamic_fps_data { + u32 hfp; + u32 hbp; + u32 hpw; + u32 clk_rate; + u32 fps; +}; + +/** + * enum dynamic_fps_update - defines fps update modes + * @DFPS_SUSPEND_RESUME_MODE: suspend/resume mode + * @DFPS_IMMEDIATE_CLK_UPDATE_MODE: update fps using clock + * @DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP: update fps using vertical timings + * @DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP: update fps using horizontal timings + * @DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP: update fps using both horizontal + * timings and clock. + * @DFPS_MODE_MAX: defines maximum limit of supported modes. + */ enum dynamic_fps_update { DFPS_SUSPEND_RESUME_MODE, DFPS_IMMEDIATE_CLK_UPDATE_MODE, DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP, DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP, + DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP, DFPS_MODE_MAX }; |
