diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 37b241b2e2..a8143c8edb 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -3855,6 +3855,8 @@ static bool _sde_crtc_wait_for_fences(struct drm_crtc *crtc) bool input_hw_fences_enable; struct sde_kms *sde_kms = _sde_crtc_get_kms(crtc); int ret; + enum sde_crtc_vm_req vm_req; + bool disable_hw_fences = false; SDE_DEBUG("\n"); @@ -3866,10 +3868,15 @@ static bool _sde_crtc_wait_for_fences(struct drm_crtc *crtc) SDE_ATRACE_BEGIN("plane_wait_input_fence"); + /* if this is the last frame on vm transition, disable hw fences */ + vm_req = sde_crtc_get_property(to_sde_crtc_state(crtc->state), CRTC_PROP_VM_REQ_STATE); + if (vm_req == VM_REQ_RELEASE) + disable_hw_fences = true; + /* update ctl hw to wait for ipcc input signal before fetch */ if (test_bit(HW_FENCE_IN_FENCES_ENABLE, sde_crtc->hwfence_features_mask) && !sde_fence_update_input_hw_fence_signal(hw_ctl, sde_kms->debugfs_hw_fence, - sde_kms->hw_mdp)) + sde_kms->hw_mdp, disable_hw_fences)) ipcc_input_signal_wait = true; /* avoid hw-fences in first frame after timing engine enable */ diff --git a/msm/sde/sde_fence.c b/msm/sde/sde_fence.c index f2890f258c..74b8037c27 100644 --- a/msm/sde/sde_fence.c +++ b/msm/sde/sde_fence.c @@ -469,7 +469,7 @@ static int _reset_hw_fence_timeline(struct sde_hw_ctl *hw_ctl, u32 flags) } int sde_fence_update_input_hw_fence_signal(struct sde_hw_ctl *hw_ctl, u32 debugfs_hw_fence, - struct sde_hw_mdp *hw_mdp) + struct sde_hw_mdp *hw_mdp, bool disable) { struct sde_hw_fence_data *data; u32 ipcc_signal_id; @@ -486,6 +486,11 @@ int sde_fence_update_input_hw_fence_signal(struct sde_hw_ctl *hw_ctl, u32 debugf ctl_id = hw_ctl->idx - CTL_0; data = &hw_ctl->hwfence_data; + if (disable) { + hw_ctl->ops.hw_fence_ctrl(hw_ctl, false, false, 0); + return -EPERM; + } + if ((debugfs_hw_fence & SDE_INPUT_HW_FENCE_TIMESTAMP) && hw_mdp->ops.hw_fence_input_timestamp_ctrl) hw_mdp->ops.hw_fence_input_timestamp_ctrl(hw_mdp, true, false); diff --git a/msm/sde/sde_fence.h b/msm/sde/sde_fence.h index 57435f4b28..87a0220078 100644 --- a/msm/sde/sde_fence.h +++ b/msm/sde/sde_fence.h @@ -192,11 +192,12 @@ int sde_fence_update_hw_fences_txq(struct sde_fence_context *ctx, bool vid_mode, * @ctl: hw ctl to update the input-fence and enable hw-fences * @debugfs_hw_fence: hw-fence timestamp debugfs value * @hw_mdp: pointer to hw_mdp to get timestamp registers + * @disable: bool to indicate if we should disable hw-fencing for this commit * * Returns: Zero on success, otherwise returns an error code. */ int sde_fence_update_input_hw_fence_signal(struct sde_hw_ctl *ctl, u32 debugfs_hw_fence, - struct sde_hw_mdp *hw_mdp); + struct sde_hw_mdp *hw_mdp, bool disable); /** * sde_fence_deinit - deinit fence container diff --git a/msm/sde/sde_hw_ctl.c b/msm/sde/sde_hw_ctl.c index fafed8cb41..87975be114 100644 --- a/msm/sde/sde_hw_ctl.c +++ b/msm/sde/sde_hw_ctl.c @@ -365,7 +365,12 @@ static inline void sde_hw_ctl_hw_fence_ctrl(struct sde_hw_ctl *ctx, bool sw_over u32 val; val = SDE_REG_READ(&ctx->hw, CTL_HW_FENCE_CTRL); - val |= (0x1 & mode) | (sw_override_set ? BIT(5) : 0) | (sw_override_clear ? BIT(4) : 0); + val |= (sw_override_set ? BIT(5) : 0) | (sw_override_clear ? BIT(4) : 0); + if (!mode) + val &= ~BIT(0); + else + val |= BIT(0); + SDE_REG_WRITE(&ctx->hw, CTL_HW_FENCE_CTRL, val); }