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

Commit ed3327ba authored by Clarence Ip's avatar Clarence Ip
Browse files

drm/msm/sde: delay rsc pre-stop for video/wb encoders



For command mode encoders on the primary display, RSC state
transitions need to be completed before the physical encoder
is disabled. Otherwise, the RSC hardware may not be able to
complete its state transitions properly.

However, for other physical encoder types, the RSC state
updates during encoder disable may potentially enable the
RSC solver, and should be postponed until after the physical
encoders have been fully disabled.

Change-Id: I39d044ca96256dbdb478a243c709bf432abf8c62
Signed-off-by: default avatarClarence Ip <cip@codeaurora.org>
parent 318cff16
Loading
Loading
Loading
Loading
+27 −5
Original line number Diff line number Diff line
@@ -2313,6 +2313,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	struct drm_connector *drm_conn = NULL;
	enum sde_intf_mode intf_mode;
	int i = 0;

	if (!drm_enc) {
@@ -2331,6 +2332,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)

	priv = drm_enc->dev->dev_private;
	sde_kms = to_sde_kms(priv->kms);
	intf_mode = sde_encoder_get_intf_mode(drm_enc);

	SDE_EVT32(DRMID(drm_enc));

@@ -2341,14 +2343,34 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
	/* wait for idle */
	sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);

	sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_PRE_STOP);
	/*
	 * For primary command mode encoders, execute the resource control
	 * pre-stop operations before the physical encoders are disabled, to
	 * allow the rsc to transition its states properly.
	 *
	 * For other encoder types, rsc should not be enabled until after
	 * they have been fully disabled, so delay the pre-stop operations
	 * until after the physical disable calls have returned.
	 */
	if (sde_enc->disp_info.is_primary && intf_mode == INTF_MODE_CMD) {
		sde_encoder_resource_control(drm_enc,
				SDE_ENC_RC_EVENT_PRE_STOP);
		for (i = 0; i < sde_enc->num_phys_encs; i++) {
			struct sde_encoder_phys *phys = sde_enc->phys_encs[i];

			if (phys && phys->ops.disable)
				phys->ops.disable(phys);
		}
	} else {
		for (i = 0; i < sde_enc->num_phys_encs; i++) {
			struct sde_encoder_phys *phys = sde_enc->phys_encs[i];

			if (phys && phys->ops.disable)
				phys->ops.disable(phys);
		}
		sde_encoder_resource_control(drm_enc,
				SDE_ENC_RC_EVENT_PRE_STOP);
	}

	/*
	 * disable dsc after the transfer is complete (for command mode)
+18 −3
Original line number Diff line number Diff line
@@ -860,6 +860,9 @@ static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc)
		sde_encoder_phys_inc_pending(phys_enc);
	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);

	if (!sde_encoder_phys_vid_is_master(phys_enc))
		goto exit;

	/*
	 * Wait for a vsync so we know the ENABLE=0 latched before
	 * the (connector) source of the vsync's gets disabled,
@@ -868,7 +871,16 @@ static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc)
	 * the settings changes for the new modeset (like new
	 * scanout buffer) don't latch properly..
	 */
	if (sde_encoder_phys_vid_is_master(phys_enc)) {
	ret = sde_encoder_phys_vid_control_vblank_irq(phys_enc, true);
	if (ret) {
		SDE_ERROR_VIDENC(vid_enc,
				"failed to enable vblank irq: %d\n",
				ret);
		SDE_EVT32(DRMID(phys_enc->parent),
				vid_enc->hw_intf->idx - INTF_0, ret,
				SDE_EVTLOG_FUNC_CASE1,
				SDE_EVTLOG_ERROR);
	} else {
		ret = _sde_encoder_phys_vid_wait_for_vblank(phys_enc, false);
		if (ret) {
			atomic_set(&phys_enc->pending_kickoff_cnt, 0);
@@ -876,10 +888,13 @@ static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc)
					"failure waiting for disable: %d\n",
					ret);
			SDE_EVT32(DRMID(phys_enc->parent),
					vid_enc->hw_intf->idx - INTF_0, ret);
					vid_enc->hw_intf->idx - INTF_0, ret,
					SDE_EVTLOG_FUNC_CASE2,
					SDE_EVTLOG_ERROR);
		}
		sde_encoder_phys_vid_control_vblank_irq(phys_enc, false);
	}

exit:
	phys_enc->enable_state = SDE_ENC_DISABLED;
}