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

Commit 94e0f608 authored by Alan Kwong's avatar Alan Kwong
Browse files

msm: sde: add rotator busy detection and reset



During power suspend event, if rotator busy is
still set given there is no outstanding request,
rotator should be reset to avoid restarting in
invalid state after power resume event. Add
rotator busy detection logic in power suspend
event and reset accordingly.

Change-Id: Ibfd965a586dca664c2c947da6796caee30d2b527
Signed-off-by: default avatarAlan Kwong <akwong@codeaurora.org>
parent cd14029c
Loading
Loading
Loading
Loading
+42 −12
Original line number Original line Diff line number Diff line
@@ -133,6 +133,9 @@
#define SDE_ROTREG_READ(base, off) \
#define SDE_ROTREG_READ(base, off) \
	readl_relaxed(base + (off))
	readl_relaxed(base + (off))


#define SDE_ROTTOP_IN_OFFLINE_MODE(_rottop_op_mode_) \
	(((_rottop_op_mode_) & ROTTOP_OP_MODE_ROT_OUT_MASK) == 0)

static const u32 sde_hw_rotator_v3_inpixfmts[] = {
static const u32 sde_hw_rotator_v3_inpixfmts[] = {
	SDE_PIX_FMT_XRGB_8888,
	SDE_PIX_FMT_XRGB_8888,
	SDE_PIX_FMT_ARGB_8888,
	SDE_PIX_FMT_ARGB_8888,
@@ -696,7 +699,7 @@ static void sde_hw_rotator_halt_vbif_xin_client(void)
/**
/**
 * sde_hw_rotator_reset - Reset rotator hardware
 * sde_hw_rotator_reset - Reset rotator hardware
 * @rot: pointer to hw rotator
 * @rot: pointer to hw rotator
 * @ctx: pointer to current rotator context during the hw hang
 * @ctx: pointer to current rotator context during the hw hang (optional)
 */
 */
static int sde_hw_rotator_reset(struct sde_hw_rotator *rot,
static int sde_hw_rotator_reset(struct sde_hw_rotator *rot,
		struct sde_hw_rotator_context *ctx)
		struct sde_hw_rotator_context *ctx)
@@ -710,13 +713,8 @@ static int sde_hw_rotator_reset(struct sde_hw_rotator *rot,
	int i, j;
	int i, j;
	unsigned long flags;
	unsigned long flags;


	if (!rot || !ctx) {
	if (!rot) {
		SDEROT_ERR("NULL rotator context\n");
		SDEROT_ERR("NULL rotator\n");
		return -EINVAL;
	}

	if (ctx->q_id >= ROT_QUEUE_MAX) {
		SDEROT_ERR("context q_id out of range: %d\n", ctx->q_id);
		return -EINVAL;
		return -EINVAL;
	}
	}


@@ -728,6 +726,15 @@ static int sde_hw_rotator_reset(struct sde_hw_rotator *rot,
	/* halt vbif xin client to ensure no pending transaction */
	/* halt vbif xin client to ensure no pending transaction */
	sde_hw_rotator_halt_vbif_xin_client();
	sde_hw_rotator_halt_vbif_xin_client();


	/* if no ctx is specified, skip ctx wake up */
	if (!ctx)
		return 0;

	if (ctx->q_id >= ROT_QUEUE_MAX) {
		SDEROT_ERR("context q_id out of range: %d\n", ctx->q_id);
		return -EINVAL;
	}

	spin_lock_irqsave(&rot->rotisr_lock, flags);
	spin_lock_irqsave(&rot->rotisr_lock, flags);


	/* update timestamp register with current context */
	/* update timestamp register with current context */
@@ -819,6 +826,11 @@ static void _sde_hw_rotator_dump_status(struct sde_hw_rotator *rot,
		SDE_ROTREG_READ(rot->mdss_base,
		SDE_ROTREG_READ(rot->mdss_base,
			REGDMA_CSR_REGDMA_FSM_STATE));
			REGDMA_CSR_REGDMA_FSM_STATE));


	SDEROT_ERR("rottop: op_mode = %x, status = %x, clk_status = %x\n",
		SDE_ROTREG_READ(rot->mdss_base, ROTTOP_OP_MODE),
		SDE_ROTREG_READ(rot->mdss_base, ROTTOP_STATUS),
		SDE_ROTREG_READ(rot->mdss_base, ROTTOP_CLK_STATUS));

	reg = SDE_ROTREG_READ(rot->mdss_base, ROT_SSPP_UBWC_ERROR_STATUS);
	reg = SDE_ROTREG_READ(rot->mdss_base, ROT_SSPP_UBWC_ERROR_STATUS);
	if (ubwcerr)
	if (ubwcerr)
		*ubwcerr = reg;
		*ubwcerr = reg;
@@ -2191,7 +2203,7 @@ void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon)
{
{
	struct sde_hw_rotator *rot;
	struct sde_hw_rotator *rot;
	u32 l_ts, h_ts, swts, hwts;
	u32 l_ts, h_ts, swts, hwts;
	u32 rotsts, regdmasts;
	u32 rotsts, regdmasts, rotopmode;


	/*
	/*
	 * Check last HW timestamp with SW timestamp before power off event.
	 * Check last HW timestamp with SW timestamp before power off event.
@@ -2216,19 +2228,37 @@ void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon)
		regdmasts = SDE_ROTREG_READ(rot->mdss_base,
		regdmasts = SDE_ROTREG_READ(rot->mdss_base,
				REGDMA_CSR_REGDMA_BLOCK_STATUS);
				REGDMA_CSR_REGDMA_BLOCK_STATUS);
		rotsts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_STATUS);
		rotsts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_STATUS);
		rotopmode = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_OP_MODE);


		SDEROT_DBG(
		SDEROT_DBG(
			"swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n",
			"swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x, rottop-opmode:0x%x\n",
				swts, hwts, regdmasts, rotsts);
				swts, hwts, regdmasts, rotsts, rotopmode);
		SDEROT_EVTLOG(swts, hwts, regdmasts, rotsts);
		SDEROT_EVTLOG(swts, hwts, regdmasts, rotsts, rotopmode);


		if ((swts != hwts) && ((regdmasts & REGDMA_BUSY) ||
		if ((swts != hwts) && ((regdmasts & REGDMA_BUSY) ||
					(rotsts & ROT_STATUS_MASK))) {
					(rotsts & ROT_STATUS_MASK))) {
			SDEROT_ERR(
			SDEROT_ERR(
				"Mismatch SWTS with HWTS: swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n",
				"Mismatch SWTS with HWTS: swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n",
				swts, hwts, regdmasts, rotsts);
				swts, hwts, regdmasts, rotsts);
			_sde_hw_rotator_dump_status(rot, NULL);
			SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus",
					"vbif_dbg_bus", "panic");
		} else if (!SDE_ROTTOP_IN_OFFLINE_MODE(rotopmode) &&
				((regdmasts & REGDMA_BUSY) ||
						(rotsts & ROT_BUSY_BIT))) {
			/*
			 * rotator can stuck in inline while mdp is detached
			 */
			SDEROT_WARN(
				"Inline Rot busy: regdma-sts:0x%x, rottop-sts:0x%x, rottop-opmode:0x%x\n",
				regdmasts, rotsts, rotopmode);
			sde_hw_rotator_reset(rot, NULL);
		} else if ((regdmasts & REGDMA_BUSY) ||
				(rotsts & ROT_BUSY_BIT)) {
			_sde_hw_rotator_dump_status(rot, NULL);
			SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus",
			SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus",
					"vbif_dbg_bus", "panic");
					"vbif_dbg_bus", "panic");
			sde_hw_rotator_reset(rot, NULL);
		}
		}


		/* Turn off rotator clock after checking rotator registers */
		/* Turn off rotator clock after checking rotator registers */
+2 −0
Original line number Original line Diff line number Diff line
@@ -50,6 +50,8 @@
#define ROTTOP_START_CTRL_TRIG_SEL_REGDMA       2
#define ROTTOP_START_CTRL_TRIG_SEL_REGDMA       2
#define ROTTOP_START_CTRL_TRIG_SEL_MDP          3
#define ROTTOP_START_CTRL_TRIG_SEL_MDP          3


#define ROTTOP_OP_MODE_ROT_OUT_MASK             (0x3 << 4)

/* SDE_ROT_SSPP:
/* SDE_ROT_SSPP:
 * OFFSET=0x0A8900
 * OFFSET=0x0A8900
 */
 */