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

Commit 12254a73 authored by Ingrid Gallardo's avatar Ingrid Gallardo Committed by Abhijith Desai
Browse files

msm: mdss: fix autorefresh disable sequence



Sequence to disable autorefresh when handoff is
done to the kernel is missing to wait for the
previous transaction to finish. This change
makes sure any previous on-going transaction
finishes before disabling autorefresh.

Change-Id: I547aea5cc82989d03963b2153e2561092fd7b36c
Signed-off-by: default avatarIngrid Gallardo <ingridg@codeaurora.org>
parent 6f6f50a2
Loading
Loading
Loading
Loading
+86 −77
Original line number Diff line number Diff line
@@ -338,6 +338,87 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_mixer *mixer,
	return 0;
}

/**
 * mdss_mdp_cmd_autorefresh_pp_done() - pp done irq callback for autorefresh
 * @arg: void pointer to the controller context.
 *
 * This function is the pp_done interrupt callback while disabling
 * autorefresh. This function does not modify the kickoff count (koff_cnt).
 */
static void mdss_mdp_cmd_autorefresh_pp_done(void *arg)
{
	struct mdss_mdp_ctl *ctl = arg;
	struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];

	if (!ctx) {
		pr_err("%s: invalid ctx\n", __func__);
		return;
	}

	mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
		ctx->current_pp_num);
	mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
		ctx->current_pp_num, NULL, NULL);

	MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num);
	complete_all(&ctx->autorefresh_ppdone);

	pr_debug("%s: ctl_num=%d intf_num=%d ctx=%d cnt=%d\n", __func__,
		ctl->num, ctl->intf_num, ctx->current_pp_num,
		atomic_read(&ctx->koff_cnt));
}

static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl)
{
	int rc;
	u32 val, line_out, intr_type = MDSS_MDP_IRQ_TYPE_PING_PONG_COMP;
	char __iomem *pp_base = ctl->mixer_left->pingpong_base;
	struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];

	line_out = mdss_mdp_pingpong_read(pp_base, MDSS_MDP_REG_PP_LINE_COUNT);

	MDSS_XLOG(ctl->num, line_out, ctl->mixer_left->roi.h);
	pr_debug("ctl:%d line_out:%d\n", ctl->num, line_out);

	if (!ctx) {
		pr_err("%s: invalid ctx\n", __func__);
		return;
	}

	if (line_out < ctl->mixer_left->roi.h) {
		reinit_completion(&ctx->autorefresh_ppdone);

		/* enable ping pong done */
		mdss_mdp_set_intr_callback(intr_type, ctx->current_pp_num,
					mdss_mdp_cmd_autorefresh_pp_done, ctl);
		mdss_mdp_irq_enable(intr_type, ctx->current_pp_num);

		/* wait for ping pong done */
		rc = wait_for_completion_timeout(&ctx->autorefresh_ppdone,
				KOFF_TIMEOUT);
		if (rc <= 0) {
			val = mdss_mdp_pingpong_read(pp_base,
				MDSS_MDP_REG_PP_LINE_COUNT);
			if (val == ctl->mixer_left->roi.h) {
				mdss_mdp_irq_clear(ctl->mdata,
					MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
					ctx->current_pp_num);
				mdss_mdp_irq_disable_nosync(intr_type,
					ctx->current_pp_num);
				mdss_mdp_set_intr_callback(intr_type,
					ctx->current_pp_num, NULL, NULL);
			} else {
				pr_err("timedout waiting for ctl%d autorefresh pp done\n",
					ctl->num);
				MDSS_XLOG(0xbad3);
				MDSS_XLOG_TOUT_HANDLER("mdp",
					"vbif", "dbg_bus", "vbif_dbg_bus",
					"panic");
			}
		}
	}
}

static bool __disable_rd_ptr_from_te(char __iomem *pingpong_base)
{
	u32 cfg;
@@ -411,7 +492,10 @@ static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_cmd_ctx *ctx,
			rd_ptr_disabled =
				__disable_rd_ptr_from_te(mixer->pingpong_base);

			/* 2. disable autorefresh  */
			/* 2. wait for previous transfer to finish */
			mdss_mdp_cmd_wait4_autorefresh_pp(ctl);

			/* 3. disable autorefresh  */
			if (is_pingpong_split(ctl->mfd))
				__disable_autorefresh(
					mdata->slave_pingpong_base);
@@ -428,7 +512,7 @@ static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_cmd_ctx *ctx,
			__disable_autorefresh(mixer->pingpong_base);
			pr_debug("%s: disabling auto refresh\n", __func__);

			/* 2. re-enable rd pointer from te (if was enabled) */
			/* 4. re-enable rd pointer from te (if was enabled) */
			if (rd_ptr_disabled)
				__enable_rd_ptr_from_te(mixer->pingpong_base);

@@ -1490,36 +1574,6 @@ static int mdss_mdp_cmd_update_lineptr(struct mdss_mdp_ctl *ctl, bool enable)
	return 0;
}

/**
 * mdss_mdp_cmd_autorefresh_pp_done() - pp done irq callback for autorefresh
 * @arg: void pointer to the controller context.
 *
 * This function is the pp_done interrupt callback while disabling
 * autorefresh. This function does not modify the kickoff count (koff_cnt).
 */
static void mdss_mdp_cmd_autorefresh_pp_done(void *arg)
{
	struct mdss_mdp_ctl *ctl = arg;
	struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];

	if (!ctx) {
		pr_err("%s: invalid ctx\n", __func__);
		return;
	}

	mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
		ctx->current_pp_num);
	mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
		ctx->current_pp_num, NULL, NULL);

	MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num);
	complete_all(&ctx->autorefresh_ppdone);

	pr_debug("%s: ctl_num=%d intf_num=%d ctx=%d cnt=%d\n", __func__,
		ctl->num, ctl->intf_num, ctx->current_pp_num,
		atomic_read(&ctx->koff_cnt));
}

static void pingpong_done_work(struct work_struct *work)
{
	u32 status;
@@ -2450,51 +2504,6 @@ static void mdss_mdp_cmd_post_programming(struct mdss_mdp_ctl *mctl)
	}
}

static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl)
{
	int rc;
	u32 val, line_out, intr_type = MDSS_MDP_IRQ_TYPE_PING_PONG_COMP;
	char __iomem *pp_base = ctl->mixer_left->pingpong_base;
	struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];

	line_out = mdss_mdp_pingpong_read(pp_base, MDSS_MDP_REG_PP_LINE_COUNT);

	MDSS_XLOG(ctl->num, line_out, ctl->mixer_left->roi.h);

	if ((line_out < ctl->mixer_left->roi.h) && line_out) {
		reinit_completion(&ctx->autorefresh_ppdone);

		/* enable ping pong done */
		mdss_mdp_set_intr_callback(intr_type, ctx->current_pp_num,
					mdss_mdp_cmd_autorefresh_pp_done, ctl);
		mdss_mdp_irq_enable(intr_type, ctx->current_pp_num);

		/* wait for ping pong done */
		rc = wait_for_completion_timeout(&ctx->autorefresh_ppdone,
				KOFF_TIMEOUT);
		if (rc <= 0) {
			val = mdss_mdp_pingpong_read(pp_base,
				MDSS_MDP_REG_PP_LINE_COUNT);
			if (val == ctl->mixer_left->roi.h) {
				mdss_mdp_irq_clear(ctl->mdata,
					MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
					ctx->current_pp_num);
				mdss_mdp_irq_disable_nosync(intr_type,
					ctx->current_pp_num);
				mdss_mdp_set_intr_callback(intr_type,
					ctx->current_pp_num, NULL, NULL);
			} else {
				pr_err("timedout waiting for ctl%d autorefresh pp done\n",
					ctl->num);
				MDSS_XLOG(0xbad3);
				MDSS_XLOG_TOUT_HANDLER("mdp",
					"vbif", "dbg_bus", "vbif_dbg_bus",
					"panic");
			}
		}
	}
}

static void mdss_mdp_cmd_autorefresh_done(void *arg)
{
	struct mdss_mdp_ctl *ctl = arg;