diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index fbf6fcc654..68c7dd5f5f 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -4626,7 +4626,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, * condition between txq update and the hw signal during ctl-done for partial updates */ if (test_bit(HW_FENCE_OUT_FENCES_ENABLE, sde_crtc->hwfence_features_mask) && !is_vid) - sde_fence_update_hw_fences_txq(sde_crtc->output_fence, false); + sde_fence_update_hw_fences_txq(sde_crtc->output_fence, false, 0); list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc != crtc) @@ -6543,6 +6543,16 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc, vfree(info); } +static bool _is_crtc_intf_mode_wb(struct drm_crtc *crtc) +{ + enum sde_intf_mode intf_mode = sde_crtc_get_intf_mode(crtc, crtc->state); + + if ((intf_mode != INTF_MODE_WB_BLOCK) && (intf_mode != INTF_MODE_WB_LINE)) + return false; + + return true; +} + static int _sde_crtc_get_output_fence(struct drm_crtc *crtc, const struct drm_crtc_state *state, uint64_t *val) { @@ -6550,6 +6560,7 @@ static int _sde_crtc_get_output_fence(struct drm_crtc *crtc, struct sde_crtc_state *cstate; uint32_t offset; bool is_vid = false; + bool is_wb = false; struct drm_encoder *encoder; struct sde_hw_ctl *hw_ctl = NULL; static u32 count; @@ -6558,10 +6569,12 @@ static int _sde_crtc_get_output_fence(struct drm_crtc *crtc, cstate = to_sde_crtc_state(state); drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) { - if (sde_encoder_check_curr_mode(encoder, - MSM_DISPLAY_VIDEO_MODE)) + if (sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_VIDEO_MODE)) is_vid = true; - if (is_vid) + else if (_is_crtc_intf_mode_wb(crtc)) + is_wb = true; + + if (is_vid || is_wb) break; } @@ -6570,7 +6583,7 @@ static int _sde_crtc_get_output_fence(struct drm_crtc *crtc, * to create a hw-fence for this ctl, whereas if hw_ctl is not passed to sde_fence, this * won't use hw-fences for this output-fence. */ - if (test_bit(HW_FENCE_OUT_FENCES_ENABLE, sde_crtc->hwfence_features_mask) && + if (!is_wb && test_bit(HW_FENCE_OUT_FENCES_ENABLE, sde_crtc->hwfence_features_mask) && (count++ % sde_crtc->hwfence_out_fences_skip)) hw_ctl = _sde_crtc_get_hw_ctl(crtc); diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 9b1b40ef12..3fd651ecba 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -3709,6 +3709,7 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc) static inline void _sde_encoder_update_retire_txq(struct sde_encoder_phys *phys) { struct sde_connector *c_conn; + int line_count; c_conn = to_sde_connector(phys->connector); if (!c_conn) { @@ -3716,8 +3717,10 @@ static inline void _sde_encoder_update_retire_txq(struct sde_encoder_phys *phys) return; } + line_count = sde_connector_get_property(phys->connector->state, + CONNECTOR_PROP_EARLY_FENCE_LINE); if (c_conn->hwfence_wb_retire_fences_enable) - sde_fence_update_hw_fences_txq(c_conn->retire_fence, false); + sde_fence_update_hw_fences_txq(c_conn->retire_fence, false, line_count); } /** @@ -3939,7 +3942,7 @@ void sde_encoder_helper_update_out_fence_txq(struct sde_encoder_virt *sde_enc, b sde_crtc = to_sde_crtc(sde_enc->crtc); SDE_EVT32(DRMID(sde_enc->crtc), is_vid); - sde_fence_update_hw_fences_txq(sde_crtc->output_fence, is_vid); + sde_fence_update_hw_fences_txq(sde_crtc->output_fence, is_vid, 0); } /** diff --git a/msm/sde/sde_fence.c b/msm/sde/sde_fence.c index 6f8faeacdc..51b50dbe20 100644 --- a/msm/sde/sde_fence.c +++ b/msm/sde/sde_fence.c @@ -251,7 +251,7 @@ int sde_fence_register_hw_fences_wait(struct sde_hw_ctl *hw_ctl, struct dma_fenc return ret; } -static int _arm_output_hw_fence(struct sde_hw_ctl *hw_ctl) +static int _arm_output_hw_fence(struct sde_hw_ctl *hw_ctl, u32 line_count) { struct sde_hw_fence_data *data; u32 ipcc_out_signal; @@ -284,12 +284,16 @@ static int _arm_output_hw_fence(struct sde_hw_ctl *hw_ctl) SDE_EVT32_VERBOSE(ctl_id, ipcc_out_signal); /* arm dpu to trigger output fence signal once ready */ - hw_ctl->ops.hw_fence_trigger_output_fence(hw_ctl, HW_FENCE_TRIGGER_SEL_CTRL_DONE); + if (line_count) + hw_ctl->ops.hw_fence_trigger_output_fence(hw_ctl, + HW_FENCE_TRIGGER_SEL_PROG_LINE_COUNT); + else + hw_ctl->ops.hw_fence_trigger_output_fence(hw_ctl, HW_FENCE_TRIGGER_SEL_CTRL_DONE); return 0; } -static int _sde_fence_arm_output_hw_fence(struct sde_fence_context *ctx) +static int _sde_fence_arm_output_hw_fence(struct sde_fence_context *ctx, u32 line_count) { struct sde_hw_ctl *hw_ctl = NULL; struct sde_fence *fc, *next; @@ -326,13 +330,13 @@ static int _sde_fence_arm_output_hw_fence(struct sde_fence_context *ctx) /* arm dpu to trigger output hw-fence ipcc signal upon completion */ if (hw_ctl) - _arm_output_hw_fence(hw_ctl); + _arm_output_hw_fence(hw_ctl, line_count); return 0; } /* update output hw_fences txq */ -int sde_fence_update_hw_fences_txq(struct sde_fence_context *ctx, bool vid_mode) +int sde_fence_update_hw_fences_txq(struct sde_fence_context *ctx, bool vid_mode, u32 line_count) { int ret = 0; struct sde_hw_fence_data *data; @@ -404,8 +408,8 @@ exit: spin_unlock(&ctx->list_lock); /* arm dpu to trigger output hw-fence ipcc signal upon completion in vid-mode */ - if (txq_updated && hw_ctl) - _sde_fence_arm_output_hw_fence(ctx); + if ((txq_updated && hw_ctl) || line_count) + _sde_fence_arm_output_hw_fence(ctx, line_count); return ret; } diff --git a/msm/sde/sde_fence.h b/msm/sde/sde_fence.h index d1822bf9df..6677bc8f74 100644 --- a/msm/sde/sde_fence.h +++ b/msm/sde/sde_fence.h @@ -175,10 +175,11 @@ int sde_fence_register_hw_fences_wait(struct sde_hw_ctl *hw_ctl, struct dma_fenc * * @ctx: sde fence context * @vid_mode: is video-mode update + * @line_count: prog line count value, must be non-zero * * Returns: Zero on success, otherwise returns an error code. */ -int sde_fence_update_hw_fences_txq(struct sde_fence_context *ctx, bool vid_mode); +int sde_fence_update_hw_fences_txq(struct sde_fence_context *ctx, bool vid_mode, u32 line_count); /** * sde_fence_update_input_hw_fence_signal - updates input-fence ipcc signal in dpu and enables