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

Commit 6340a37f authored by Lloyd Atkinson's avatar Lloyd Atkinson
Browse files

drm/msm/sde: check in video encoder irq if ctl was flushed



Add logic in the SDE video encoder vblank irq handler to verify
that the hardware actually flushed before decrementing the
pending flush counter. This prevents incorrectly signaling that
the buffer was flipped.

Change-Id: Idd723f80a8a7f5f596654a784c3a76abe75c4f19
Signed-off-by: default avatarLloyd Atkinson <latkinso@codeaurora.org>
parent 79d42bd7
Loading
Loading
Loading
Loading
+21 −4
Original line number Diff line number Diff line
@@ -337,23 +337,40 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
{
	struct sde_encoder_phys_vid *vid_enc = arg;
	struct sde_encoder_phys *phys_enc;
	struct sde_hw_ctl *hw_ctl;
	unsigned long lock_flags;
	int new_cnt;
	u32 flush_register = 0;
	int new_cnt = -1, old_cnt = -1;

	if (!vid_enc)
		return;

	phys_enc = &vid_enc->base;
	hw_ctl = phys_enc->hw_ctl;

	if (phys_enc->parent_ops.handle_vblank_virt)
		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
				phys_enc);

	old_cnt  = atomic_read(&phys_enc->pending_kickoff_cnt);

	/*
	 * only decrement the pending flush count if we've actually flushed
	 * hardware. due to sw irq latency, vblank may have already happened
	 * so we need to double-check with hw that it accepted the flush bits
	 */
	spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
	new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);
	SDE_EVT32_IRQ(DRMID(phys_enc->parent), vid_enc->hw_intf->idx - INTF_0,
			new_cnt);
	if (hw_ctl && hw_ctl->ops.get_flush_register)
		flush_register = hw_ctl->ops.get_flush_register(hw_ctl);

	if (flush_register == 0)
		new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt,
				-1, 0);
	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);

	SDE_EVT32_IRQ(DRMID(phys_enc->parent), vid_enc->hw_intf->idx - INTF_0,
			old_cnt, new_cnt, flush_register);

	/* Signal any waiting atomic commit thread */
	wake_up_all(&phys_enc->pending_kickoff_wq);
}
+7 −0
Original line number Diff line number Diff line
@@ -107,6 +107,12 @@ static inline void sde_hw_ctl_trigger_flush(struct sde_hw_ctl *ctx)
	SDE_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
}

static inline u32 sde_hw_ctl_get_flush_register(struct sde_hw_ctl *ctx)
{
	struct sde_hw_blk_reg_map *c = &ctx->hw;

	return SDE_REG_READ(c, CTL_FLUSH);
}

static inline uint32_t sde_hw_ctl_get_bitmask_sspp(struct sde_hw_ctl *ctx,
	enum sde_sspp sspp)
@@ -529,6 +535,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
	ops->update_pending_flush = sde_hw_ctl_update_pending_flush;
	ops->get_pending_flush = sde_hw_ctl_get_pending_flush;
	ops->trigger_flush = sde_hw_ctl_trigger_flush;
	ops->get_flush_register = sde_hw_ctl_get_flush_register;
	ops->trigger_start = sde_hw_ctl_trigger_start;
	ops->setup_intf_cfg = sde_hw_ctl_intf_cfg;
	ops->reset = sde_hw_ctl_reset_control;
+7 −0
Original line number Diff line number Diff line
@@ -126,6 +126,13 @@ struct sde_hw_ctl_ops {
	 */
	void (*trigger_flush)(struct sde_hw_ctl *ctx);

	/**
	 * Read the value of the flush register
	 * @ctx       : ctl path ctx pointer
	 * @Return: value of the ctl flush register.
	 */
	u32 (*get_flush_register)(struct sde_hw_ctl *ctx);

	/**
	 * Setup ctl_path interface config
	 * @ctx