Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db2811f3 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mdss: display: Add support for variable refresh rate"

parents d808ff1f 6f1e602d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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.
+57 −26
Original line number Diff line number Diff line
@@ -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) {
@@ -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);
@@ -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__);
	}
@@ -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__);
+2 −1
Original line number Diff line number Diff line
@@ -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;

+4 −1
Original line number Diff line number Diff line
@@ -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;
}
+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
@@ -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;
@@ -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