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

Commit b3818159 authored by Jin Li's avatar Jin Li
Browse files

drm/msm: clear interface configuration during encoder disable



During atomic commit for encoder disable, driver needs to clear
the interface configuration inside control path. Otherwise, it
may conflict with interface setting from next encoder enable,
and cause hardware hang.

Change-Id: I3102b745479efc10963b2a884a5a23693a13e4c3
Signed-off-by: default avatarJin Li <jinl@codeaurora.org>
parent 80daa7e7
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -374,12 +374,22 @@ static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc)
{
	struct sde_encoder_phys_cmd *cmd_enc =
		to_sde_encoder_phys_cmd(phys_enc);
	struct sde_hw_intf_cfg intf_cfg = { 0 };
	struct sde_hw_ctl *ctl = phys_enc->hw_ctl;
	u32 flush_mask = 0;

	DBG("intf %d, pp %d", cmd_enc->intf_idx, cmd_enc->hw_pp->idx);

	if (WARN_ON(phys_enc->enable_state == SDE_ENC_DISABLED))
		return;

	if (WARN_ON(!phys_enc->hw_ctl->ops.setup_intf_cfg))
		return;

	phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg);
	ctl->ops.get_bitmask_intf(ctl, &flush_mask, cmd_enc->intf_idx);
	ctl->ops.update_pending_flush(ctl, flush_mask);

	sde_encoder_phys_cmd_unregister_pp_irq(phys_enc,
			cmd_enc->pp_tx_done_irq_idx);
	sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
+10 −0
Original line number Diff line number Diff line
@@ -465,6 +465,10 @@ static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc)
	unsigned long lock_flags;
	struct sde_encoder_phys_vid *vid_enc =
			to_sde_encoder_phys_vid(phys_enc);
	struct sde_hw_intf_cfg intf_cfg = { 0 };
	struct sde_hw_intf *intf = vid_enc->hw_intf;
	struct sde_hw_ctl *ctl = phys_enc->hw_ctl;
	u32 flush_mask = 0;

	if (!vid_enc->hw_intf || !phys_enc->hw_ctl) {
		SDE_ERROR("invalid hw: intf %pK ctl %pK\n", vid_enc->hw_intf,
@@ -477,13 +481,19 @@ static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc)
	if (WARN_ON(!vid_enc->hw_intf->ops.enable_timing))
		return;

	if (WARN_ON(!phys_enc->hw_ctl->ops.setup_intf_cfg))
		return;

	if (WARN_ON(phys_enc->enable_state == SDE_ENC_DISABLED))
		return;

	spin_lock_irqsave(&phys_enc->spin_lock, lock_flags);
	phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg);
	vid_enc->hw_intf->ops.enable_timing(vid_enc->hw_intf, 0);
	reinit_completion(&vid_enc->vblank_completion);
	phys_enc->enable_state = SDE_ENC_DISABLED;
	ctl->ops.get_bitmask_intf(ctl, &flush_mask, intf->idx);
	ctl->ops.update_pending_flush(ctl, flush_mask);
	spin_unlock_irqrestore(&phys_enc->spin_lock, lock_flags);

	/*
+7 −0
Original line number Diff line number Diff line
@@ -779,6 +779,7 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc)
{
	struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
	struct sde_hw_wb *hw_wb = wb_enc->hw_wb;
	struct sde_hw_intf_cfg *intf_cfg = &wb_enc->intf_cfg;

	SDE_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0);

@@ -787,6 +788,8 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc)
		return;
	}

	memset(intf_cfg, 0, sizeof(struct sde_hw_intf_cfg));

	if (wb_enc->frame_count != wb_enc->kickoff_count) {
		SDE_DEBUG("[wait_for_done: wb:%d, frame:%u, kickoff:%u]\n",
				hw_wb->idx - WB_0, wb_enc->frame_count,
@@ -799,6 +802,10 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc)
		phys_enc->hw_cdm->ops.disable(phys_enc->hw_cdm);
	}

	if (phys_enc->hw_ctl && phys_enc->hw_ctl->ops.setup_intf_cfg)
		phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl,
				intf_cfg);

	phys_enc->enable_state = SDE_ENC_DISABLED;
}