Loading Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +3 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,9 @@ Optional properties: 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. - qcom,mdss-dsi-bl-pmic-control-type: A string that specifies the implementation of backlight control for this panel. "bl_ctrl_pwm" = Backlight controlled by PWM gpio. Loading drivers/video/msm/mdss/mdss_dsi.c +57 −26 Original line number Diff line number Diff line Loading @@ -659,6 +659,31 @@ 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) { u32 hsync_period, vsync_period; u32 new_dsi_v_total, current_dsi_v_total; vsync_period = mdss_panel_get_vtotal(&pdata->panel_info); hsync_period = mdss_panel_get_htotal(&pdata->panel_info); current_dsi_v_total = MIPI_INP((ctrl_pdata->ctrl_base) + 0x2C); new_dsi_v_total = ((vsync_period - 1) << 16) | (hsync_period - 1); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, (current_dsi_v_total | 0x8000000)); if (new_dsi_v_total & 0x8000000) { MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, new_dsi_v_total); } else { MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, (new_dsi_v_total | 0x8000000)); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, (new_dsi_v_total & 0x7ffffff)); } pdata->panel_info.mipi.frame_rate = new_fps; } else { rc = mdss_dsi_clk_div_config (&ctrl_pdata->panel_data.panel_info, new_fps); if (rc) { Loading @@ -667,16 +692,15 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) return rc; } ctrl_pdata->pclk_rate = ctrl_pdata->panel_data.panel_info.mipi.dsi_pclk_rate; pdata->panel_info.mipi.dsi_pclk_rate; ctrl_pdata->byte_clk_rate = ctrl_pdata->panel_data.panel_info.clk_rate / 8; pdata->panel_info.clk_rate / 8; if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004); ctrl_pdata->panel_data.panel_info.mipi.frame_rate = new_fps; pdata->panel_info.mipi.frame_rate = new_fps; dsi_ctrl &= ~0x2; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl); Loading @@ -687,6 +711,7 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl); } } } else { pr_debug("%s: Panel is already at this FPS\n", __func__); } Loading Loading @@ -1220,6 +1245,12 @@ int dsi_panel_device_register(struct device_node *pan_node, DFPS_IMMEDIATE_CLK_UPDATE_MODE; pr_debug("%s: dfps mode: Immediate clk\n", __func__); } else if (!strcmp(data, "dfps_immediate_porch_mode")) { pinfo->dfps_update = DFPS_IMMEDIATE_PORCH_UPDATE_MODE; pr_debug("%s: dfps mode: Immediate porch\n", __func__); } else { pr_debug("%s: dfps to default mode\n", __func__); Loading drivers/video/msm/mdss/mdss_mdp.h +2 −1 Original line number Diff line number Diff line Loading @@ -186,7 +186,8 @@ struct mdss_mdp_ctl { struct mdss_mdp_vsync_handler *); int (*remove_vsync_handler) (struct mdss_mdp_ctl *, struct mdss_mdp_vsync_handler *); int (*config_fps_fnc) (struct mdss_mdp_ctl *ctl, int new_fps); int (*config_fps_fnc) (struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl, int new_fps); struct blocking_notifier_head notifier_head; Loading drivers/video/msm/mdss/mdss_mdp_ctl.c +4 −1 Original line number Diff line number Diff line Loading @@ -2240,9 +2240,12 @@ static int mdss_mdp_mixer_update(struct mdss_mdp_mixer *mixer) int mdss_mdp_ctl_update_fps(struct mdss_mdp_ctl *ctl, int fps) { int ret = 0; struct mdss_mdp_ctl *sctl = NULL; sctl = mdss_mdp_get_split_ctl(ctl); if (ctl->config_fps_fnc) ret = ctl->config_fps_fnc(ctl, fps); ret = ctl->config_fps_fnc(ctl, sctl, fps); return ret; } Loading drivers/video/msm/mdss/mdss_mdp_intf_video.c +92 −2 Original line number Diff line number Diff line /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -466,7 +466,63 @@ static void mdss_mdp_video_underrun_intr_done(void *arg) ctl->underrun_cnt); } static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, int new_fps) static int mdss_mdp_video_vfp_fps_update(struct mdss_mdp_ctl *ctl, int new_fps) { int curr_fps; u32 add_v_lines = 0; u32 current_vsync_period_f0, new_vsync_period_f0; struct mdss_panel_data *pdata; struct mdss_mdp_video_ctx *ctx; u32 vsync_period, hsync_period; ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data; if (!ctx) { pr_err("invalid ctx\n"); return -ENODEV; } pdata = ctl->panel_data; if (pdata == NULL) { pr_err("%s: Invalid panel data\n", __func__); return -EINVAL; } vsync_period = mdss_panel_get_vtotal(&pdata->panel_info); hsync_period = mdss_panel_get_htotal(&pdata->panel_info); 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; } vsync_period = mdss_panel_get_vtotal(&pdata->panel_info); current_vsync_period_f0 = mdp_video_read(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0); new_vsync_period_f0 = (vsync_period * hsync_period); mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0, current_vsync_period_f0 | 0x800000); if (new_vsync_period_f0 & 0x800000) { mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0, new_vsync_period_f0); } else { mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0, new_vsync_period_f0 | 0x800000); mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0, new_vsync_period_f0 & 0x7fffff); } return 0; } static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl, int new_fps) { struct mdss_mdp_video_ctx *ctx; struct mdss_panel_data *pdata; Loading Loading @@ -529,6 +585,40 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, int new_fps) ctl->force_screen_state = MDSS_SCREEN_DEFAULT; mdss_mdp_display_commit(ctl, NULL); mdss_mdp_display_wait4comp(ctl); } else if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE){ if (!ctx->timegen_en) { pr_err("TG is OFF. DFPS mode invalid\n"); return -EINVAL; } video_vsync_irq_enable(ctl, true); INIT_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); rc = 0; video_vsync_irq_disable(ctl); rc = mdss_mdp_video_vfp_fps_update(ctl, new_fps); if (rc < 0) { pr_err("%s: Error during DFPS\n", __func__); return rc; } if (sctl) { rc = mdss_mdp_video_vfp_fps_update(sctl, new_fps); if (rc < 0) { pr_err("%s: DFPS error\n", __func__); return rc; } } rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_UPDATE_FPS, (void *)new_fps); WARN(rc, "intf %d panel fps update error (%d)\n", ctl->intf_num, rc); } else { pr_err("intf %d panel, unknown FPS mode\n", ctl->intf_num); Loading Loading
Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +3 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,9 @@ Optional properties: 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. - qcom,mdss-dsi-bl-pmic-control-type: A string that specifies the implementation of backlight control for this panel. "bl_ctrl_pwm" = Backlight controlled by PWM gpio. Loading
drivers/video/msm/mdss/mdss_dsi.c +57 −26 Original line number Diff line number Diff line Loading @@ -659,6 +659,31 @@ 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) { u32 hsync_period, vsync_period; u32 new_dsi_v_total, current_dsi_v_total; vsync_period = mdss_panel_get_vtotal(&pdata->panel_info); hsync_period = mdss_panel_get_htotal(&pdata->panel_info); current_dsi_v_total = MIPI_INP((ctrl_pdata->ctrl_base) + 0x2C); new_dsi_v_total = ((vsync_period - 1) << 16) | (hsync_period - 1); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, (current_dsi_v_total | 0x8000000)); if (new_dsi_v_total & 0x8000000) { MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, new_dsi_v_total); } else { MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, (new_dsi_v_total | 0x8000000)); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, (new_dsi_v_total & 0x7ffffff)); } pdata->panel_info.mipi.frame_rate = new_fps; } else { rc = mdss_dsi_clk_div_config (&ctrl_pdata->panel_data.panel_info, new_fps); if (rc) { Loading @@ -667,16 +692,15 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) return rc; } ctrl_pdata->pclk_rate = ctrl_pdata->panel_data.panel_info.mipi.dsi_pclk_rate; pdata->panel_info.mipi.dsi_pclk_rate; ctrl_pdata->byte_clk_rate = ctrl_pdata->panel_data.panel_info.clk_rate / 8; pdata->panel_info.clk_rate / 8; if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004); ctrl_pdata->panel_data.panel_info.mipi.frame_rate = new_fps; pdata->panel_info.mipi.frame_rate = new_fps; dsi_ctrl &= ~0x2; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl); Loading @@ -687,6 +711,7 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl); } } } else { pr_debug("%s: Panel is already at this FPS\n", __func__); } Loading Loading @@ -1220,6 +1245,12 @@ int dsi_panel_device_register(struct device_node *pan_node, DFPS_IMMEDIATE_CLK_UPDATE_MODE; pr_debug("%s: dfps mode: Immediate clk\n", __func__); } else if (!strcmp(data, "dfps_immediate_porch_mode")) { pinfo->dfps_update = DFPS_IMMEDIATE_PORCH_UPDATE_MODE; pr_debug("%s: dfps mode: Immediate porch\n", __func__); } else { pr_debug("%s: dfps to default mode\n", __func__); Loading
drivers/video/msm/mdss/mdss_mdp.h +2 −1 Original line number Diff line number Diff line Loading @@ -186,7 +186,8 @@ struct mdss_mdp_ctl { struct mdss_mdp_vsync_handler *); int (*remove_vsync_handler) (struct mdss_mdp_ctl *, struct mdss_mdp_vsync_handler *); int (*config_fps_fnc) (struct mdss_mdp_ctl *ctl, int new_fps); int (*config_fps_fnc) (struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl, int new_fps); struct blocking_notifier_head notifier_head; Loading
drivers/video/msm/mdss/mdss_mdp_ctl.c +4 −1 Original line number Diff line number Diff line Loading @@ -2240,9 +2240,12 @@ static int mdss_mdp_mixer_update(struct mdss_mdp_mixer *mixer) int mdss_mdp_ctl_update_fps(struct mdss_mdp_ctl *ctl, int fps) { int ret = 0; struct mdss_mdp_ctl *sctl = NULL; sctl = mdss_mdp_get_split_ctl(ctl); if (ctl->config_fps_fnc) ret = ctl->config_fps_fnc(ctl, fps); ret = ctl->config_fps_fnc(ctl, sctl, fps); return ret; } Loading
drivers/video/msm/mdss/mdss_mdp_intf_video.c +92 −2 Original line number Diff line number Diff line /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -466,7 +466,63 @@ static void mdss_mdp_video_underrun_intr_done(void *arg) ctl->underrun_cnt); } static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, int new_fps) static int mdss_mdp_video_vfp_fps_update(struct mdss_mdp_ctl *ctl, int new_fps) { int curr_fps; u32 add_v_lines = 0; u32 current_vsync_period_f0, new_vsync_period_f0; struct mdss_panel_data *pdata; struct mdss_mdp_video_ctx *ctx; u32 vsync_period, hsync_period; ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data; if (!ctx) { pr_err("invalid ctx\n"); return -ENODEV; } pdata = ctl->panel_data; if (pdata == NULL) { pr_err("%s: Invalid panel data\n", __func__); return -EINVAL; } vsync_period = mdss_panel_get_vtotal(&pdata->panel_info); hsync_period = mdss_panel_get_htotal(&pdata->panel_info); 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; } vsync_period = mdss_panel_get_vtotal(&pdata->panel_info); current_vsync_period_f0 = mdp_video_read(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0); new_vsync_period_f0 = (vsync_period * hsync_period); mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0, current_vsync_period_f0 | 0x800000); if (new_vsync_period_f0 & 0x800000) { mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0, new_vsync_period_f0); } else { mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0, new_vsync_period_f0 | 0x800000); mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0, new_vsync_period_f0 & 0x7fffff); } return 0; } static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl, int new_fps) { struct mdss_mdp_video_ctx *ctx; struct mdss_panel_data *pdata; Loading Loading @@ -529,6 +585,40 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, int new_fps) ctl->force_screen_state = MDSS_SCREEN_DEFAULT; mdss_mdp_display_commit(ctl, NULL); mdss_mdp_display_wait4comp(ctl); } else if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE){ if (!ctx->timegen_en) { pr_err("TG is OFF. DFPS mode invalid\n"); return -EINVAL; } video_vsync_irq_enable(ctl, true); INIT_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); rc = 0; video_vsync_irq_disable(ctl); rc = mdss_mdp_video_vfp_fps_update(ctl, new_fps); if (rc < 0) { pr_err("%s: Error during DFPS\n", __func__); return rc; } if (sctl) { rc = mdss_mdp_video_vfp_fps_update(sctl, new_fps); if (rc < 0) { pr_err("%s: DFPS error\n", __func__); return rc; } } rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_UPDATE_FPS, (void *)new_fps); WARN(rc, "intf %d panel fps update error (%d)\n", ctl->intf_num, rc); } else { pr_err("intf %d panel, unknown FPS mode\n", ctl->intf_num); Loading