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

Commit d5312332 authored by Kuogee Hsieh's avatar Kuogee Hsieh Committed by Stephen Boyd
Browse files

mdss: display: wait for ping pong done before update registers



Ping pong done interrupt indicates previous mdp kickoff has been
completed and it is ready for next kickoff. Non-double buffered
registers updated can only be executed after ping pong done to avoid
unexpected side effects when updating hardware while mdp still active.

CRs-fixed: 481408
Change-Id: Ia06ad8dc7663e31132fe066095a3911aecb5d3e4
Signed-off-by: default avatarKuogee Hsieh <khsieh@codeaurora.org>
parent a7465056
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -157,6 +157,7 @@ struct mdss_mdp_ctl {
	int (*prepare_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
	int (*display_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
	int (*wait_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
	int (*wait_pingpong) (struct mdss_mdp_ctl *ctl, void *arg);
	u32 (*read_line_cnt_fnc) (struct mdss_mdp_ctl *);
	int (*add_vsync_handler) (struct mdss_mdp_ctl *,
					struct mdss_mdp_vsync_handler *);
@@ -436,6 +437,7 @@ int mdss_mdp_mixer_pipe_update(struct mdss_mdp_pipe *pipe, int params_changed);
int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe);
int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
int mdss_mdp_display_wait4comp(struct mdss_mdp_ctl *ctl);
int mdss_mdp_display_wait4pingpong(struct mdss_mdp_ctl *ctl);
int mdss_mdp_display_wakeup_time(struct mdss_mdp_ctl *ctl,
				 ktime_t *wakeup_time);

+21 −0
Original line number Diff line number Diff line
@@ -1442,6 +1442,27 @@ int mdss_mdp_display_wait4comp(struct mdss_mdp_ctl *ctl)
	return ret;
}

int mdss_mdp_display_wait4pingpong(struct mdss_mdp_ctl *ctl)
{
	int ret;

	ret = mutex_lock_interruptible(&ctl->lock);
	if (ret)
		return ret;

	if (!ctl->power_on) {
		mutex_unlock(&ctl->lock);
		return 0;
	}

	if (ctl->wait_pingpong)
		ret = ctl->wait_pingpong(ctl, NULL);

	mutex_unlock(&ctl->lock);

	return ret;
}

int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg)
{
	struct mdss_mdp_ctl *sctl = NULL;
+29 −25
Original line number Diff line number Diff line
@@ -335,32 +335,12 @@ static void mdss_mdp_cmd_chk_clock(struct mdss_mdp_cmd_ctx *ctx)
	mutex_unlock(&ctx->clk_mtx);
}

static int mdss_mdp_cmd_wait4comp(struct mdss_mdp_ctl *ctl, void *arg)
{
	struct mdss_mdp_cmd_ctx *ctx;
	int rc;

	ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
	if (!ctx) {
		pr_err("invalid ctx\n");
		return -ENODEV;
	}

	pr_debug("%s: intf_num=%d ctx=%p\n", __func__, ctl->intf_num, ctx);

	rc = wait_for_completion_interruptible_timeout(&ctx->vsync_comp,
			KOFF_TIMEOUT);
	WARN(rc <= 0, "cmd kickoff timed out (%d) ctl=%d\n", rc, ctl->num);

	return 0;
}

int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
{
	struct mdss_mdp_cmd_ctx *ctx;
	unsigned long flags;
	int need_wait = 0;
	int rc;
	int rc = 0;

	ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
	if (!ctx) {
@@ -377,11 +357,29 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
			__func__, need_wait, ctl->intf_num, ctx);

	if (need_wait) {
		rc = wait_for_completion_interruptible_timeout(
		rc = wait_for_completion_timeout(
				&ctx->pp_comp, KOFF_TIMEOUT);

		WARN(rc <= 0, "cmd kickoff timed out (%d) ctl=%d\n",
		if (rc <= 0) {
			WARN(1, "cmd kickoff timed out (%d) ctl=%d\n",
						rc, ctl->num);
			rc = -EPERM;
		} else
			rc = 0;
	}

	return rc;
}

int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
{
	struct mdss_mdp_cmd_ctx *ctx;
	int rc;

	ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
	if (!ctx) {
		pr_err("invalid ctx\n");
		return -ENODEV;
	}

	if (ctx->panel_on == 0) {
@@ -456,6 +454,12 @@ 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);

	ctl->stop_fnc = NULL;
	ctl->display_fnc = NULL;
	ctl->wait_pingpong = NULL;
	ctl->add_vsync_handler = NULL;
	ctl->remove_vsync_handler = NULL;

	pr_debug("%s:-\n", __func__);

	return 0;
@@ -519,7 +523,7 @@ int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl)

	ctl->stop_fnc = mdss_mdp_cmd_stop;
	ctl->display_fnc = mdss_mdp_cmd_kickoff;
	ctl->wait_fnc = mdss_mdp_cmd_wait4comp;
	ctl->wait_pingpong = mdss_mdp_cmd_wait4pingpong;
	ctl->add_vsync_handler = mdss_mdp_cmd_vsync_ctrl;
	ctl->remove_vsync_handler = mdss_mdp_cmd_vsync_ctrl;

+8 −0
Original line number Diff line number Diff line
@@ -701,6 +701,14 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd)

	mutex_lock(&mdp5_data->ov_lock);
	mutex_lock(&mfd->lock);

	ret = mdss_mdp_display_wait4pingpong(mdp5_data->ctl);
	if (ret) {
		mutex_unlock(&mfd->lock);
		mutex_unlock(&mdp5_data->ov_lock);
		return ret;
	}

	list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
		struct mdss_mdp_data *buf;
		if (pipe->back_buf.num_planes) {