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

Commit baa56353 authored by Alan Kwong's avatar Alan Kwong Committed by Narendra Muppalla
Browse files

drm/msm/sde: correct to use sync vblank request for commit



Current sde_wait_for_commit_done is calling asynchronous
drm_crtc_vblank_get/put to enable/disable vblank interrupt.
However, drm_crtc_vblank_get/put submit the vblank request
to a workqueue for later execution. As a result, vblank
irq is not get/put properly prior/after the commit operation
in sde_wait_for_commit_done.

Replace async drm_crtc_vblank_get/put with sync sde_crtc_vblank,
and use reference count in encoder to enable/disable interrupts.

Change-Id: Iccc83983d56b75717eda9c401a54dfe77e945fed
Signed-off-by: default avatarAlan Kwong <akwong@codeaurora.org>
parent 5a3ac754
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -141,6 +141,7 @@ enum sde_enc_enable_state {
 * @spin_lock:		Lock for IRQ purposes
 * @mode_3d:		3D mux configuration
 * @enable_state:	Enable state tracking
 * @vblank_refcount:	Reference count of vblank request
 */
struct sde_encoder_phys {
	struct drm_encoder *parent;
@@ -157,6 +158,7 @@ struct sde_encoder_phys {
	spinlock_t spin_lock;
	enum sde_3d_blend_mode mode_3d;
	enum sde_enc_enable_state enable_state;
	atomic_t vblank_refcount;
};

/**
+26 −12
Original line number Diff line number Diff line
@@ -377,20 +377,27 @@ static int sde_encoder_phys_cmd_control_vblank_irq(
		SDE_ERROR("invalid encoder\n");
		return -EINVAL;
	}
	SDE_DEBUG_CMDENC(cmd_enc, "enable %d\n", enable);

	/* Slave encoders don't report vblank */
	if (sde_encoder_phys_cmd_is_master(phys_enc)) {
		if (enable)
	if (!sde_encoder_phys_cmd_is_master(phys_enc))
		return 0;

	SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n",
			__builtin_return_address(0),
			enable, atomic_read(&phys_enc->vblank_refcount));

	MSM_EVTMSG(phys_enc->parent->dev, NULL, enable,
			atomic_read(&phys_enc->vblank_refcount));

	if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
		ret = sde_encoder_phys_cmd_register_pp_irq(phys_enc,
				SDE_IRQ_TYPE_PING_PONG_RD_PTR,
				&cmd_enc->pp_rd_ptr_irq_idx,
				sde_encoder_phys_cmd_pp_rd_ptr_irq,
				"pp_rd_ptr");
		else
	else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
		ret = sde_encoder_phys_cmd_unregister_pp_irq(phys_enc,
				cmd_enc->pp_rd_ptr_irq_idx);
	}

	if (ret)
		SDE_ERROR_CMDENC(cmd_enc,
@@ -475,6 +482,12 @@ static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc)
	atomic_set(&cmd_enc->pending_cnt, 0);
	wake_up_all(&cmd_enc->pp_tx_done_wq);
	phys_enc->enable_state = SDE_ENC_DISABLED;

	if (atomic_read(&phys_enc->vblank_refcount))
		SDE_ERROR("enc:%d role:%d invalid vblank refcount %d\n",
				phys_enc->parent->base.id,
				phys_enc->split_role,
				atomic_read(&phys_enc->vblank_refcount));
}

static void sde_encoder_phys_cmd_destroy(struct sde_encoder_phys *phys_enc)
@@ -602,6 +615,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
	cmd_enc->stream_sel = 0;
	phys_enc->enable_state = SDE_ENC_DISABLED;
	atomic_set(&cmd_enc->pending_cnt, 0);
	atomic_set(&phys_enc->vblank_refcount, 0);

	init_waitqueue_head(&cmd_enc->pp_tx_done_wq);

+21 −8
Original line number Diff line number Diff line
@@ -466,15 +466,21 @@ static int sde_encoder_phys_vid_control_vblank_irq(
		return -EINVAL;
	}

	SDE_DEBUG_VIDENC(vid_enc, "enable %d\n", enable);

	/* Slave encoders don't report vblank */
	if (sde_encoder_phys_vid_is_master(phys_enc)) {
		if (enable)
	if (!sde_encoder_phys_vid_is_master(phys_enc))
		return 0;

	SDE_DEBUG_VIDENC(vid_enc, "[%pS] enable=%d/%d\n",
			__builtin_return_address(0),
			enable, atomic_read(&phys_enc->vblank_refcount));

	MSM_EVTMSG(phys_enc->parent->dev, NULL, enable,
			atomic_read(&phys_enc->vblank_refcount));

	if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
		ret = sde_encoder_phys_vid_register_irq(phys_enc);
		else
	else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
		ret = sde_encoder_phys_vid_unregister_irq(phys_enc);
	}

	if (ret)
		SDE_ERROR_VIDENC(vid_enc,
@@ -568,6 +574,12 @@ static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc)
		sde_encoder_phys_vid_wait_for_vblank(vid_enc);
		sde_encoder_phys_vid_control_vblank_irq(phys_enc, false);
	}

	if (atomic_read(&phys_enc->vblank_refcount))
		SDE_ERROR("enc:%d role:%d invalid vblank refcount %d\n",
				phys_enc->parent->base.id,
				phys_enc->split_role,
				atomic_read(&phys_enc->vblank_refcount));
}

static void sde_encoder_phys_vid_destroy(struct sde_encoder_phys *phys_enc)
@@ -749,6 +761,7 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init(
	phys_enc->intf_mode = INTF_MODE_VIDEO;
	spin_lock_init(&phys_enc->spin_lock);
	init_completion(&vid_enc->vblank_completion);
	atomic_set(&phys_enc->vblank_refcount, 0);

	DRM_INFO_ONCE("intf %d: 3d blend modes not yet supported\n",
			vid_enc->hw_intf->idx);
+2 −2
Original line number Diff line number Diff line
@@ -282,7 +282,7 @@ static void sde_wait_for_commit_done(struct msm_kms *kms,
	}

	 /* ref count the vblank event and interrupts while we wait for it */
	if (drm_crtc_vblank_get(crtc))
	if (sde_crtc_vblank(crtc, true))
		return;

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
@@ -302,7 +302,7 @@ static void sde_wait_for_commit_done(struct msm_kms *kms,
	}

	 /* release vblank event ref count */
	drm_crtc_vblank_put(crtc);
	sde_crtc_vblank(crtc, false);
}

static void sde_kms_prepare_fence(struct msm_kms *kms,