summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev
diff options
context:
space:
mode:
authorAjay Singh Parmar <aparmar@codeaurora.org>2016-03-25 23:15:10 -0700
committerKyle Yan <kyan@codeaurora.org>2016-04-28 16:45:26 -0700
commit50d6b2a04e6987dcc8e3d0240af912c159365227 (patch)
tree413591035c82a50adf6bf9700fd72f4dca810b9d /drivers/video/fbdev
parent6fae8899dc8c34668ad35d6a8161e4480474e455 (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.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c14
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c59
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h27
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
};