diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 90d2777417..75b62d864d 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -2225,6 +2225,11 @@ int sde_encoder_hw_fence_error_handle(struct drm_encoder *drm_enc) } } + if (phys_enc->hw_ctl->ops.clear_flush_mask) { + phys_enc->hw_ctl->ops.clear_flush_mask(phys_enc->hw_ctl, true); + SDE_EVT32(DRMID(drm_enc), SDE_EVTLOG_FUNC_CASE2); + } + phys_enc->sde_hw_fence_error_status = false; SDE_EVT32(DRMID(drm_enc), SDE_EVTLOG_FUNC_EXIT); return rc; @@ -4234,6 +4239,12 @@ static inline void _sde_encoder_trigger_flush(struct drm_encoder *drm_enc, ctl->ops.update_bitmask(ctl, SDE_HW_FLUSH_PERIPH, phys->hw_intf->idx, 1); } + /* update flush mask to ignore fence error frame commit */ + if (ctl->ops.clear_flush_mask && phys->fence_error_handle_in_progress) { + ctl->ops.clear_flush_mask(ctl, false); + SDE_EVT32(DRMID(drm_enc), SDE_EVTLOG_FUNC_CASE1); + } + if ((extra_flush && extra_flush->pending_flush_mask) && ctl->ops.update_pending_flush) ctl->ops.update_pending_flush(ctl, extra_flush); diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index a3952bd174..9a1694c5a4 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/msm/sde/sde_encoder_phys.h @@ -132,6 +132,7 @@ struct sde_encoder_virt_ops { * @handle_post_kickoff: Do any work necessary post-kickoff work * @trigger_flush: Process flush event on physical encoder * @trigger_start: Process start event on physical encoder + * @clear_flush_mask: clear flush mask * @needs_single_flush: Whether encoder slaves need to be flushed * @setup_misr: Sets up MISR, enable and disables based on sysfs * @collect_misr: Collects MISR data on frame update @@ -186,6 +187,7 @@ struct sde_encoder_phys_ops { void (*handle_post_kickoff)(struct sde_encoder_phys *phys_enc); void (*trigger_flush)(struct sde_encoder_phys *phys_enc); void (*trigger_start)(struct sde_encoder_phys *phys_enc); + void (*clear_flush_mask)(struct sde_encoder_phys *phys_enc, bool clear); bool (*needs_single_flush)(struct sde_encoder_phys *phys_enc); void (*setup_misr)(struct sde_encoder_phys *phys_encs, diff --git a/msm/sde/sde_hw_ctl.c b/msm/sde/sde_hw_ctl.c index 453000bff5..39aff3c73e 100644 --- a/msm/sde/sde_hw_ctl.c +++ b/msm/sde/sde_hw_ctl.c @@ -29,6 +29,7 @@ #define CTL_SW_RESET 0x030 #define CTL_SW_RESET_OVERRIDE 0x060 #define CTL_STATUS 0x064 +#define CTL_FLUSH_MASK 0x090 #define CTL_LAYER_EXTN_OFFSET 0x40 #define CTL_ROT_TOP 0x0C0 #define CTL_ROT_FLUSH 0x0C4 @@ -476,6 +477,15 @@ static inline int sde_hw_ctl_trigger_pending(struct sde_hw_ctl *ctx) return 0; } +static inline int sde_hw_ctl_clear_flush_mask(struct sde_hw_ctl *ctx, bool clear) +{ + if (!ctx) + return -EINVAL; + + SDE_REG_WRITE(&ctx->hw, CTL_FLUSH_MASK, clear ? 0xffffffff : 0); + return 0; +} + static inline int sde_hw_ctl_clear_pending_flush(struct sde_hw_ctl *ctx) { if (!ctx) @@ -1476,6 +1486,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, ops->update_bitmask = sde_hw_ctl_update_bitmask; ops->get_ctl_intf = sde_hw_ctl_get_intf; } + ops->clear_flush_mask = sde_hw_ctl_clear_flush_mask; ops->clear_pending_flush = sde_hw_ctl_clear_pending_flush; ops->get_pending_flush = sde_hw_ctl_get_pending_flush; ops->get_flush_register = sde_hw_ctl_get_flush_register; diff --git a/msm/sde/sde_hw_ctl.h b/msm/sde/sde_hw_ctl.h index a9c19af33a..61df8084de 100644 --- a/msm/sde/sde_hw_ctl.h +++ b/msm/sde/sde_hw_ctl.h @@ -284,6 +284,13 @@ struct sde_hw_ctl_ops { */ void (*uidle_enable)(struct sde_hw_ctl *ctx, bool enable); + /** + * clear flush mask + * @ctx : ctl path ctx pointer + * @clear : true to clear the flush mask + */ + int (*clear_flush_mask)(struct sde_hw_ctl *ctx, bool clear); + /** * Clear the value of the cached pending_flush_mask * No effect on hardware