From 9a33a2a1fd3ae755c1f9f5240e4260cceee6c643 Mon Sep 17 00:00:00 2001 From: Christina Oliveira Date: Fri, 29 Apr 2022 10:03:09 -0700 Subject: [PATCH] disp: msm: sde: hw_fence update autorefresh disable sequence This change updates the autorefresh disable sequence to manually trigger output hw_fence during the transition. This is required since on the last autorefresh frame HW will not trigger the output fence. Change-Id: I6789fc6b51421524f88dcbdd1a063ae947646ae4 Signed-off-by: Christina Oliveira --- msm/sde/sde_encoder_phys.h | 2 ++ msm/sde/sde_encoder_phys_cmd.c | 18 ++++++++++++++++-- msm/sde/sde_hw_ctl.c | 7 +++++++ msm/sde/sde_hw_ctl.h | 6 ++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index 1e4681845c..0e719c8f0d 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/msm/sde/sde_encoder_phys.h @@ -311,6 +311,7 @@ struct sde_encoder_irq { * @frame_trigger_mode: frame trigger mode indication for command * mode display * @recovered: flag set to true when recovered from pp timeout + * @autorefresh_disable_trans: flag set to true during autorefresh disable transition */ struct sde_encoder_phys { struct drm_encoder *parent; @@ -358,6 +359,7 @@ struct sde_encoder_phys { int vfp_cached; enum frame_trigger_mode_type frame_trigger_mode; bool recovered; + bool autorefresh_disable_trans; }; static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys) diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index 5dc9427b48..193c707dfb 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -196,11 +196,23 @@ static void _sde_encoder_phys_signal_frame_done(struct sde_encoder_phys *phys_en spin_unlock(phys_enc->enc_spinlock); } - if (ctl && ctl->ops.get_scheduler_status) + if (ctl->ops.get_scheduler_status) scheduler_status = ctl->ops.get_scheduler_status(ctl); SDE_EVT32_IRQ(DRMID(phys_enc->parent), ctl->idx - CTL_0, - phys_enc->hw_pp->idx - PINGPONG_0, event, scheduler_status); + phys_enc->hw_pp->idx - PINGPONG_0, event, scheduler_status, + phys_enc->autorefresh_disable_trans); + + /* + * For hw-fences, in the last frame during the autorefresh disable transition + * hw won't trigger the output-fence signal once the frame is done, therefore + * sw must trigger the override to force the signal here + */ + if (phys_enc->autorefresh_disable_trans) { + if (ctl->ops.trigger_output_fence_override) + ctl->ops.trigger_output_fence_override(ctl); + phys_enc->autorefresh_disable_trans = false; + } /* Signal any waiting atomic commit thread */ wake_up_all(&phys_enc->pending_kickoff_wq); @@ -1881,6 +1893,8 @@ static void _sde_encoder_phys_disable_autorefresh(struct sde_encoder_phys *phys_ sde_encoder_phys_cmd_connect_te(phys_enc, false); _sde_encoder_phys_cmd_config_autorefresh(phys_enc, 0); + phys_enc->autorefresh_disable_trans = true; + if (sde_kms && sde_kms->catalog && (sde_kms->catalog->autorefresh_disable_seq == AUTOREFRESH_DISABLE_SEQ1)) { _sde_encoder_autorefresh_disable_seq1(phys_enc); diff --git a/msm/sde/sde_hw_ctl.c b/msm/sde/sde_hw_ctl.c index 7a01e3b797..6d5da122f8 100644 --- a/msm/sde/sde_hw_ctl.c +++ b/msm/sde/sde_hw_ctl.c @@ -60,6 +60,7 @@ #define CTL_OUTPUT_FENCE_CTRL 0x25C #define CTL_OUTPUT_FENCE_ID 0x260 #define CTL_HW_FENCE_STATUS 0x278 +#define CTL_OUTPUT_FENCE_SW_OVERRIDE 0x27C #define CTL_MIXER_BORDER_OUT BIT(24) #define CTL_FLUSH_MASK_ROT BIT(27) @@ -371,6 +372,11 @@ static inline void sde_hw_ctl_trigger_sw_override(struct sde_hw_ctl *ctx) SDE_REG_WRITE(&ctx->hw, CTL_FENCE_READY_SW_OVERRIDE, 0x1); } +static inline void sde_hw_ctl_trigger_output_fence_override(struct sde_hw_ctl *ctx) +{ + SDE_REG_WRITE(&ctx->hw, CTL_OUTPUT_FENCE_SW_OVERRIDE, 0x1); +} + static inline int sde_hw_ctl_trigger_start(struct sde_hw_ctl *ctx) { if (!ctx) @@ -1426,6 +1432,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, 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; + ops->trigger_output_fence_override = sde_hw_ctl_trigger_output_fence_override; } if (cap & BIT(SDE_CTL_UIDLE)) diff --git a/msm/sde/sde_hw_ctl.h b/msm/sde/sde_hw_ctl.h index 22bc45a35f..e1b148357b 100644 --- a/msm/sde/sde_hw_ctl.h +++ b/msm/sde/sde_hw_ctl.h @@ -177,6 +177,12 @@ struct sde_hw_ctl_ops { */ void (*hw_fence_ctrl)(struct sde_hw_ctl *ctx, bool sw_set, bool sw_clear, u32 mode); + /** + * override to trigger the signal for the output hw-fence + * @ctx : ctl path ctx pointer + */ + void (*trigger_output_fence_override)(struct sde_hw_ctl *ctx); + /** * trigger hw fence fence-ready sw override * @ctx : ctl path ctx pointer