msm: mdss: add DFPS horizontal front porch support

Add DFPS horizontal front porch support in addition to
vertical front porch. It adjust horizontal front porches
as needed to achieve specified new frame rate.

Change-Id: I05bccc4f515ba45a39642171799117584ae057ad
(cherry picked from commit 842c510f0759426535112d14a72a1c7658f430bd)
[veeras@codeaurora.org: Done as part of 3.18 upgrade
Removed msm8939-cdp.dtsi, msm8939-mtp.dtsi, msm8939-qrd-skuk.dtsi
from this commit]
Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
This commit is contained in:
Kuogee Hsieh 2014-10-31 15:58:12 -07:00 committed by David Keitel
parent bca18b11fc
commit 4518cd302d
5 changed files with 101 additions and 25 deletions

View file

@ -147,12 +147,15 @@ Optional properties:
- qcom,mdss-dsi-pan-enable-dynamic-fps: Boolean used to enable change in frame rate dynamically.
- qcom,mdss-dsi-pan-fps-update: A string that specifies when to change the frame rate.
"dfps_suspend_resume_mode"= FPS change request is
implemented during suspend/resume.
implemented during suspend/resume.
"dfps_immediate_clk_mode" = FPS change request is
implemented immediately using DSI clocks.
"dfps_immediate_porch_mode" = FPS change request is
implemented immediately by changing panel porch
values.
implemented immediately using DSI clocks.
"dfps_immediate_porch_mode_hfp" = FPS change request is
implemented immediately by changing panel horizontal
front porch values.
"dfps_immediate_porch_mode_vfp" = FPS change request is
implemented immediately by changing panel vertical
front porch values.
- qcom,min-refresh-rate: Minimum refresh rate supported by the panel.
- qcom,max-refresh-rate: Maximum refresh rate supported by the panel. If max refresh
rate is not specified, then the frame rate of the panel in

View file

@ -870,7 +870,7 @@ static void __mdss_dsi_update_video_mode_total(struct mdss_panel_data *pdata,
}
ctrl_rev = MIPI_INP(ctrl_pdata->ctrl_base);
/* Flush DSI TIMING registers for 8916/8939 */
if (ctrl_rev == MDSS_DSI_HW_REV_103_1)
if (ctrl_pdata->timing_db_mode)
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x1e4, 0x1);
ctrl_pdata->panel_data.panel_info.mipi.frame_rate = new_fps;
@ -1075,7 +1075,9 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps)
if (new_fps !=
ctrl_pdata->panel_data.panel_info.mipi.frame_rate) {
if (pdata->panel_info.dfps_update
== DFPS_IMMEDIATE_PORCH_UPDATE_MODE) {
== DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP ||
pdata->panel_info.dfps_update
== DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) {
__mdss_dsi_update_video_mode_total(pdata, new_fps);
if (sctrl_pdata) {

View file

@ -1356,9 +1356,14 @@ static void mdss_dsi_parse_dfps_config(struct device_node *pan_node,
} else if (!strcmp(data, "dfps_immediate_clk_mode")) {
pinfo->dfps_update = DFPS_IMMEDIATE_CLK_UPDATE_MODE;
pr_debug("dfps mode: Immediate clk\n");
} else if (!strcmp(data, "dfps_immediate_porch_mode")) {
pinfo->dfps_update = DFPS_IMMEDIATE_PORCH_UPDATE_MODE;
pr_debug("dfps mode: Immediate porch\n");
} else if (!strcmp(data, "dfps_immediate_porch_mode_hfp")) {
pinfo->dfps_update =
DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP;
pr_debug("dfps mode: Immediate porch HFP\n");
} else if (!strcmp(data, "dfps_immediate_porch_mode_vfp")) {
pinfo->dfps_update =
DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP;
pr_debug("dfps mode: Immediate porch VFP\n");
} else {
pinfo->dfps_update = DFPS_SUSPEND_RESUME_MODE;
pr_debug("default dfps mode: suspend/resume\n");

View file

@ -658,27 +658,76 @@ static void mdss_mdp_video_underrun_intr_done(void *arg)
schedule_work(&ctl->recover_work);
}
static int mdss_mdp_video_timegen_update(struct mdss_mdp_video_ctx *ctx,
struct mdss_panel_info *pinfo)
{
u32 hsync_period, vsync_period;
u32 hsync_start_x, hsync_end_x, display_v_start, display_v_end;
u32 display_hctl, hsync_ctl;
hsync_period = mdss_panel_get_htotal(pinfo, true);
vsync_period = mdss_panel_get_vtotal(pinfo);
display_v_start = ((pinfo->lcdc.v_pulse_width +
pinfo->lcdc.v_back_porch) * hsync_period) +
pinfo->lcdc.hsync_skew;
display_v_end = ((vsync_period - pinfo->lcdc.v_front_porch) *
hsync_period) + pinfo->lcdc.hsync_skew - 1;
hsync_start_x = pinfo->lcdc.h_back_porch + pinfo->lcdc.h_pulse_width;
hsync_end_x = hsync_period - pinfo->lcdc.h_front_porch - 1;
hsync_ctl = (hsync_period << 16) | pinfo->lcdc.h_pulse_width;
display_hctl = (hsync_end_x << 16) | hsync_start_x;
mdp_video_write(ctx, MDSS_MDP_REG_INTF_HSYNC_CTL, hsync_ctl);
mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0,
vsync_period * hsync_period);
mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PULSE_WIDTH_F0,
pinfo->lcdc.v_pulse_width * hsync_period);
mdp_video_write(ctx, MDSS_MDP_REG_INTF_DISPLAY_HCTL, display_hctl);
mdp_video_write(ctx, MDSS_MDP_REG_INTF_DISPLAY_V_START_F0,
display_v_start);
mdp_video_write(ctx, MDSS_MDP_REG_INTF_DISPLAY_V_END_F0, display_v_end);
return 0;
}
static int mdss_mdp_video_hfp_fps_update(struct mdss_mdp_video_ctx *ctx,
struct mdss_panel_data *pdata, int new_fps)
{
int curr_fps;
int add_h_pixels = 0;
int hsync_period;
int diff;
hsync_period = mdss_panel_get_htotal(&pdata->panel_info, true);
curr_fps = mdss_panel_get_framerate(&pdata->panel_info);
diff = curr_fps - new_fps;
add_h_pixels = mult_frac(hsync_period, diff, new_fps);
pdata->panel_info.lcdc.h_front_porch += add_h_pixels;
mdss_mdp_video_timegen_update(ctx, &pdata->panel_info);
return 0;
}
static int mdss_mdp_video_vfp_fps_update(struct mdss_mdp_video_ctx *ctx,
struct mdss_panel_data *pdata, int new_fps)
{
int curr_fps;
u32 add_v_lines = 0;
int add_v_lines = 0;
u32 current_vsync_period_f0, new_vsync_period_f0;
u32 vsync_period, hsync_period;
int vsync_period, hsync_period;
int diff;
vsync_period = mdss_panel_get_vtotal(&pdata->panel_info);
hsync_period = mdss_panel_get_htotal(&pdata->panel_info, true);
curr_fps = mdss_panel_get_framerate(&pdata->panel_info);
if (curr_fps > new_fps) {
add_v_lines = mult_frac(vsync_period,
(curr_fps - new_fps), new_fps);
pdata->panel_info.lcdc.v_front_porch += add_v_lines;
} else {
add_v_lines = mult_frac(vsync_period,
(new_fps - curr_fps), new_fps);
pdata->panel_info.lcdc.v_front_porch -= add_v_lines;
}
diff = curr_fps - new_fps;
add_v_lines = mult_frac(vsync_period, diff, new_fps);
pdata->panel_info.lcdc.v_front_porch += add_v_lines;
vsync_period = mdss_panel_get_vtotal(&pdata->panel_info);
current_vsync_period_f0 = mdp_video_read(ctx,
@ -700,6 +749,20 @@ static int mdss_mdp_video_vfp_fps_update(struct mdss_mdp_video_ctx *ctx,
return 0;
}
static int mdss_mdp_video_fps_update(struct mdss_mdp_video_ctx *ctx,
struct mdss_panel_data *pdata, int new_fps)
{
int rc;
if (pdata->panel_info.dfps_update ==
DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP)
rc = mdss_mdp_video_hfp_fps_update(ctx, pdata, new_fps);
else
rc = mdss_mdp_video_vfp_fps_update(ctx, pdata, new_fps);
return rc;
}
static int mdss_mdp_video_dfps_wait4vsync(struct mdss_mdp_ctl *ctl)
{
int rc = 0;
@ -836,7 +899,9 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl,
WARN(rc, "intf %d panel fps update error (%d)\n",
ctl->intf_num, rc);
} else if (pdata->panel_info.dfps_update
== DFPS_IMMEDIATE_PORCH_UPDATE_MODE) {
== DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP ||
pdata->panel_info.dfps_update
== DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP) {
bool wait4vsync;
unsigned long flags;
if (!ctx->timegen_en) {
@ -867,13 +932,13 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl,
goto exit_dfps;
}
rc = mdss_mdp_video_vfp_fps_update(ctx, pdata, new_fps);
rc = mdss_mdp_video_fps_update(ctx, pdata, new_fps);
if (rc < 0) {
pr_err("%s: Error during DFPS\n", __func__);
goto exit_dfps;
}
if (sctx) {
rc = mdss_mdp_video_vfp_fps_update(sctx,
rc = mdss_mdp_video_fps_update(sctx,
pdata->next, new_fps);
if (rc < 0) {
pr_err("%s: DFPS error\n", __func__);

View file

@ -304,7 +304,8 @@ struct edp_panel_info {
enum dynamic_fps_update {
DFPS_SUSPEND_RESUME_MODE,
DFPS_IMMEDIATE_CLK_UPDATE_MODE,
DFPS_IMMEDIATE_PORCH_UPDATE_MODE,
DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP,
DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP,
};
enum lvds_mode {