diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index 3511197f86..5dc9427b48 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -269,15 +269,16 @@ static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) struct sde_hw_pp_vsync_info info[MAX_CHANNELS_PER_ENC] = {{0}}; struct sde_encoder_phys_cmd_te_timestamp *te_timestamp; unsigned long lock_flags; + u32 fence_ready = 0; - if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf) + if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf || !phys_enc->hw_ctl) return; SDE_ATRACE_BEGIN("rd_ptr_irq"); cmd_enc = to_sde_encoder_phys_cmd(phys_enc); ctl = phys_enc->hw_ctl; - if (ctl && ctl->ops.get_scheduler_status) + if (ctl->ops.get_scheduler_status) scheduler_status = ctl->ops.get_scheduler_status(ctl); spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); @@ -290,13 +291,16 @@ static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) } spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); + if ((scheduler_status != 0x1) && ctl->ops.get_hw_fence_status) + fence_ready = ctl->ops.get_hw_fence_status(ctl); + sde_encoder_helper_get_pp_line_count(phys_enc->parent, info); SDE_EVT32_IRQ(DRMID(phys_enc->parent), info[0].pp_idx, info[0].intf_idx, info[0].wr_ptr_line_count, info[0].intf_frame_count, info[1].pp_idx, info[1].intf_idx, info[1].wr_ptr_line_count, info[1].intf_frame_count, - scheduler_status); + scheduler_status, fence_ready); if (phys_enc->parent_ops.handle_vblank_virt) phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent, diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index 4622f14e26..6b2cdeeea1 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/msm/sde/sde_encoder_phys_vid.c @@ -491,6 +491,7 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) int new_cnt = -1, old_cnt = -1; u32 event = 0; int pend_ret_fence_cnt = 0; + u32 fence_ready = -1; if (!phys_enc) return; @@ -510,7 +511,7 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) old_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); - if (hw_ctl && hw_ctl->ops.get_flush_register) + if (hw_ctl->ops.get_flush_register) flush_register = hw_ctl->ops.get_flush_register(hw_ctl); if (flush_register) @@ -528,7 +529,7 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) } not_flushed: - if (hw_ctl && hw_ctl->ops.get_reset) + if (hw_ctl->ops.get_reset) reset_status = hw_ctl->ops.get_reset(hw_ctl); spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); @@ -545,12 +546,16 @@ not_flushed: phys_enc->hw_intf->ops.get_status(phys_enc->hw_intf, &intf_status); + if (flush_register && hw_ctl->ops.get_hw_fence_status) + fence_ready = hw_ctl->ops.get_hw_fence_status(hw_ctl); + SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0, old_cnt, atomic_read(&phys_enc->pending_kickoff_cnt), reset_status ? SDE_EVTLOG_ERROR : 0, flush_register, event, atomic_read(&phys_enc->pending_retire_fence_cnt), - intf_status.frame_count, intf_status.line_count); + intf_status.frame_count, intf_status.line_count, + fence_ready); /* Signal any waiting atomic commit thread */ wake_up_all(&phys_enc->pending_kickoff_wq); diff --git a/msm/sde/sde_hw_ctl.c b/msm/sde/sde_hw_ctl.c index b5a3317bc6..7a01e3b797 100644 --- a/msm/sde/sde_hw_ctl.c +++ b/msm/sde/sde_hw_ctl.c @@ -59,6 +59,7 @@ #define CTL_INPUT_FENCE_ID 0x258 #define CTL_OUTPUT_FENCE_CTRL 0x25C #define CTL_OUTPUT_FENCE_ID 0x260 +#define CTL_HW_FENCE_STATUS 0x278 #define CTL_MIXER_BORDER_OUT BIT(24) #define CTL_FLUSH_MASK_ROT BIT(27) @@ -340,6 +341,11 @@ static inline void sde_hw_ctl_update_output_fence(struct sde_hw_ctl *ctx, SDE_REG_WRITE(&ctx->hw, CTL_OUTPUT_FENCE_ID, val); } +static inline int sde_hw_ctl_get_hw_fence_status(struct sde_hw_ctl *ctx) +{ + return SDE_REG_READ(&ctx->hw, CTL_HW_FENCE_STATUS); +} + static inline void sde_hw_ctl_trigger_output_fence(struct sde_hw_ctl *ctx, u32 trigger_sel) { u32 val = ((trigger_sel & 0xF) << 4) | 0x1; @@ -1419,6 +1425,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, ops->hw_fence_trigger_output_fence = sde_hw_ctl_trigger_output_fence; ops->hw_fence_ctrl = sde_hw_ctl_hw_fence_ctrl; ops->hw_fence_trigger_sw_override = sde_hw_ctl_trigger_sw_override; + ops->get_hw_fence_status = sde_hw_ctl_get_hw_fence_status; } if (cap & BIT(SDE_CTL_UIDLE)) diff --git a/msm/sde/sde_hw_ctl.h b/msm/sde/sde_hw_ctl.h index 2f70354f3e..22bc45a35f 100644 --- a/msm/sde/sde_hw_ctl.h +++ b/msm/sde/sde_hw_ctl.h @@ -190,6 +190,13 @@ struct sde_hw_ctl_ops { */ void (*hw_fence_trigger_output_fence)(struct sde_hw_ctl *ctx, u32 trigger_sel); + /** + * get hw fence status + * @ctx : ctl path ctx pointer + * @Return: fence status + */ + int (*get_hw_fence_status)(struct sde_hw_ctl *ctx); + /** * update output hw fence ipcc client_id and signal_id * @ctx : ctl path ctx pointer