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

Commit a8986062 authored by Ujwal Patel's avatar Ujwal Patel
Browse files

msm: mdss: reset ping-pong registers when display is turned off



Ping-pong registers are used for tear check when command mode panel
is used. They are used for frame buffer compression configuration if
panel supports it. But if video mode panel is used, like HDMI or eDP,
those registers should be at their reset value otherwise it can cause
unpredictable hw state and results in under-runs. To avoid this, reset
ping-pong registers when panel is turned off.

Change-Id: If792c71ac584550a24fd3424481b34179fbf1d77
Signed-off-by: default avatarUjwal Patel <ujwalp@codeaurora.org>
parent ff1ff8e0
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -2097,14 +2097,20 @@ int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl)

	mdss_mdp_hist_intr_setup(&mdata->hist_intr, MDSS_IRQ_SUSPEND);

	if (ctl->stop_fnc)
	if (ctl->stop_fnc) {
		ret = ctl->stop_fnc(ctl);
	else
		if (ctl->panel_data->panel_info.fbc.enabled)
			mdss_mdp_ctl_fbc_enable(0, ctl->mixer_left,
				&ctl->panel_data->panel_info);
	} else {
		pr_warn("no stop func for ctl=%d\n", ctl->num);
	}

	if (sctl && sctl->stop_fnc) {
		ret = sctl->stop_fnc(sctl);

		if (ctl->panel_data->panel_info.fbc.enabled)
			mdss_mdp_ctl_fbc_enable(0, sctl->mixer_left,
				&sctl->panel_data->panel_info);
		mdss_mdp_ctl_split_display_enable(0, ctl, sctl);
	}

+57 −44
Original line number Diff line number Diff line
@@ -101,17 +101,18 @@ exit:


static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_ctl *ctl,
				      struct mdss_mdp_mixer *mixer)
	struct mdss_mdp_mixer *mixer, bool enable)
{
	struct mdss_mdp_pp_tear_check *te;
	struct mdss_mdp_pp_tear_check *te = NULL;
	struct mdss_panel_info *pinfo;
	u32 vsync_clk_speed_hz, total_lines, vclks_line, cfg;
	u32 vsync_clk_speed_hz, total_lines, vclks_line, cfg = 0;

	if (IS_ERR_OR_NULL(ctl->panel_data)) {
		pr_err("no panel data\n");
		return -ENODEV;
	}

	if (enable) {
		pinfo = &ctl->panel_data->panel_info;
		te = &ctl->panel_data->panel_info.te;

@@ -146,39 +147,50 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_ctl *ctl,
			 te->vsync_init_val, te->rd_ptr_irq, te->start_pos);
		pr_debug("thrd_start =%d thrd_cont=%d\n",
			te->sync_threshold_start, te->sync_threshold_continue);
	}

	mdss_mdp_pingpong_write(mixer->pingpong_base,
		MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
	mdss_mdp_pingpong_write(mixer->pingpong_base,
		MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT, te->sync_cfg_height);
		MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT,
		te ? te->sync_cfg_height : 0);
	mdss_mdp_pingpong_write(mixer->pingpong_base,
		MDSS_MDP_REG_PP_VSYNC_INIT_VAL, te->vsync_init_val);
		MDSS_MDP_REG_PP_VSYNC_INIT_VAL,
		te ? te->vsync_init_val : 0);
	mdss_mdp_pingpong_write(mixer->pingpong_base,
		MDSS_MDP_REG_PP_RD_PTR_IRQ, te->rd_ptr_irq);
		MDSS_MDP_REG_PP_RD_PTR_IRQ,
		te ? te->rd_ptr_irq : 0);
	mdss_mdp_pingpong_write(mixer->pingpong_base,
		MDSS_MDP_REG_PP_START_POS, te->start_pos);
		MDSS_MDP_REG_PP_START_POS,
		te ? te->start_pos : 0);
	mdss_mdp_pingpong_write(mixer->pingpong_base,
		MDSS_MDP_REG_PP_SYNC_THRESH,
		((te->sync_threshold_continue << 16) |
		 te->sync_threshold_start));
		te ? ((te->sync_threshold_continue << 16) |
		 te->sync_threshold_start) : 0);
	mdss_mdp_pingpong_write(mixer->pingpong_base,
		MDSS_MDP_REG_PP_TEAR_CHECK_EN, te->tear_check_en);
		MDSS_MDP_REG_PP_TEAR_CHECK_EN,
		te ? te->tear_check_en : 0);

	return 0;
}

static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_ctl *ctl)
static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_ctl *ctl, bool enable)
{
	struct mdss_mdp_mixer *mixer;
	int rc = 0;
	struct mdss_mdp_mixer *mixer;

	mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
	if (mixer) {
		rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer);
		rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer, enable);
		if (rc)
			goto err;
	}

	if (!(ctl->opmode & MDSS_MDP_CTL_OP_PACK_3D_ENABLE)) {
		mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_RIGHT);
		if (mixer)
		rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer);
			rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer, enable);
	}
 err:
	return rc;
}
@@ -210,7 +222,7 @@ static inline void mdss_mdp_cmd_clk_on(struct mdss_mdp_cmd_ctx *ctx)
			mdss_mdp_ctl_restore(ctx->ctl);
			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);

			if (mdss_mdp_cmd_tearcheck_setup(ctx->ctl))
			if (mdss_mdp_cmd_tearcheck_setup(ctx->ctl, true))
				pr_warn("tearcheck setup failed\n");
			ctx->idle_pc = false;
		} else {
@@ -819,6 +831,8 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl)

		ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_OFF, NULL);
		WARN(ret, "intf %d unblank error (%d)\n", ctl->intf_num, ret);

		mdss_mdp_cmd_tearcheck_setup(ctl, false);
	}

	memset(ctx, 0, sizeof(*ctx));
@@ -896,8 +910,7 @@ int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl)
	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
				   mdss_mdp_cmd_pingpong_done, ctl);

	ret = mdss_mdp_cmd_tearcheck_setup(ctl);

	ret = mdss_mdp_cmd_tearcheck_setup(ctl, true);
	if (ret) {
		pr_err("tearcheck setup failed\n");
		return ret;