From 48f118202c03ce140a474ee83af9d7411caec41a Mon Sep 17 00:00:00 2001 From: Yojana Juadi Date: Thu, 7 Sep 2023 16:52:24 +0530 Subject: [PATCH] disp: msm: sde: wait for autorefresh_status to be idle in prepare kickoff If cont splash is enabled, wait for autorefresh_status to be idle for 1 vsync in prepare kickoff. This patch also prevents entering to rsc_solver_mode if autorefresh_status is busy. Change-Id: Ic4458dcbe8e06ff6f338dd264eb9371365120dd1 Signed-off-by: Yojana Juadi --- msm/sde/sde_encoder.c | 72 +++++++++++++++++----------------- msm/sde/sde_encoder_phys.h | 2 + msm/sde/sde_encoder_phys_cmd.c | 32 ++++++++++++++- 3 files changed, 68 insertions(+), 38 deletions(-) diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 4b813b88..32d20700 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -332,6 +332,16 @@ static bool _sde_encoder_is_autorefresh_enabled( CONNECTOR_PROP_AUTOREFRESH) ? true : false; } +static bool _sde_encoder_is_autorefresh_status_busy(struct sde_encoder_virt *sde_enc) +{ + if (!sde_enc->cur_master || !sde_enc->cur_master->hw_intf || + !sde_enc->cur_master->hw_intf->ops.get_autorefresh_status) + return false; + + return sde_enc->cur_master->hw_intf->ops.get_autorefresh_status( + sde_enc->cur_master->hw_intf); +} + static void sde_configure_qdss(struct sde_encoder_virt *sde_enc, struct sde_hw_qdss *hw_qdss, struct sde_encoder_phys *phys, bool enable) @@ -1498,28 +1508,6 @@ static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc, } } -static void _sde_encoder_wait_for_vsync_on_autorefresh_busy(struct sde_encoder_phys *phys_enc) -{ - u32 autorefresh_status; - int ret = 0; - - if (!phys_enc || !phys_enc->hw_intf || !phys_enc->hw_intf->ops.get_autorefresh_status) { - SDE_ERROR("invalid params\n"); - return; - } - - autorefresh_status = phys_enc->hw_intf->ops.get_autorefresh_status(phys_enc->hw_intf); - if (autorefresh_status) { - ret = sde_encoder_wait_for_event(phys_enc->parent, MSM_ENC_VBLANK); - if (ret) { - autorefresh_status = phys_enc->hw_intf->ops.get_autorefresh_status( - phys_enc->hw_intf); - SDE_ERROR("wait for vblank timed out, autorefresh_status:%d\n", - autorefresh_status); - } - } -} - int sde_encoder_helper_switch_vsync(struct drm_encoder *drm_enc, bool watchdog_te) { @@ -1715,7 +1703,8 @@ static int _sde_encoder_update_rsc_client( qsync_mode = sde_connector_get_qsync_mode( sde_enc->cur_master->connector); sde_enc->autorefresh_solver_disable = - _sde_encoder_is_autorefresh_enabled(sde_enc) ? true : false; + _sde_encoder_is_autorefresh_status_busy(sde_enc) || + _sde_encoder_is_autorefresh_enabled(sde_enc); } /* left primary encoder keep vote */ @@ -3359,6 +3348,28 @@ static void sde_encoder_wait_for_vsync_event_complete(struct sde_encoder_virt *s } } +static void _sde_encoder_helper_virt_disable(struct drm_encoder *drm_enc) +{ + int i; + struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); + + if (!sde_encoder_in_clone_mode(drm_enc)) { + /* disable autorefresh */ + for (i = 0; i < sde_enc->num_phys_encs; i++) { + struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; + + if (phys && phys->ops.disable_autorefresh && + phys->ops.wait_for_vsync_on_autorefresh_busy) { + phys->ops.disable_autorefresh(phys); + phys->ops.wait_for_vsync_on_autorefresh_busy(phys); + } + } + + /* wait for idle */ + sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE); + } +} + static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc = NULL; @@ -3406,20 +3417,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) SDE_EVT32(DRMID(drm_enc)); - if (!sde_encoder_in_clone_mode(drm_enc)) { - /* disable autorefresh */ - for (i = 0; i < sde_enc->num_phys_encs; i++) { - struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; - - if (phys && phys->ops.disable_autorefresh) { - phys->ops.disable_autorefresh(phys); - _sde_encoder_wait_for_vsync_on_autorefresh_busy(phys); - } - } - - /* wait for idle */ - sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE); - } + _sde_encoder_helper_virt_disable(drm_enc); _sde_encoder_input_handler_unregister(drm_enc); diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index e5c065da..f7363b21 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/msm/sde/sde_encoder_phys.h @@ -144,6 +144,7 @@ struct sde_encoder_virt_ops { * count and underrun line count * @add_to_minidump: Add this phys_enc data to minidumps * @disable_autorefresh: Disable autorefresh + * @wait_for_vsync_on_autorefresh_busy: Wait for vsync if autorefresh status busy */ struct sde_encoder_phys_ops { @@ -198,6 +199,7 @@ struct sde_encoder_phys_ops { u32 (*get_underrun_line_count)(struct sde_encoder_phys *phys); void (*add_to_minidump)(struct sde_encoder_phys *phys); void (*disable_autorefresh)(struct sde_encoder_phys *phys); + void (*wait_for_vsync_on_autorefresh_busy)(struct sde_encoder_phys *phys_enc); }; /** diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index ce2705b4..a5793045 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -1436,11 +1436,34 @@ static void sde_encoder_phys_cmd_get_hw_resources( hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_CMD; } +static void _sde_encoder_phys_wait_for_vsync_on_autorefresh_busy(struct sde_encoder_phys *phys_enc) +{ + u32 autorefresh_status; + int ret = 0; + + if (!phys_enc || !phys_enc->hw_intf || !phys_enc->hw_intf->ops.get_autorefresh_status) { + SDE_ERROR("invalid params\n"); + return; + } + + autorefresh_status = phys_enc->hw_intf->ops.get_autorefresh_status(phys_enc->hw_intf); + if (autorefresh_status) { + ret = sde_encoder_wait_for_event(phys_enc->parent, MSM_ENC_VBLANK); + if (ret) { + autorefresh_status = phys_enc->hw_intf->ops.get_autorefresh_status( + phys_enc->hw_intf); + SDE_ERROR("wait for vblank timed out, autorefresh_status:%d\n", + autorefresh_status); + } + } +} + static int sde_encoder_phys_cmd_prepare_for_kickoff( struct sde_encoder_phys *phys_enc, struct sde_encoder_kickoff_params *params) { struct sde_hw_tear_check tc_cfg = {0}; + struct sde_encoder_virt *sde_enc; struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); int ret = 0; @@ -1453,10 +1476,11 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0); phys_enc->frame_trigger_mode = params->frame_trigger_mode; + sde_enc = to_sde_encoder_virt(phys_enc->parent); SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(&phys_enc->pending_kickoff_cnt), atomic_read(&cmd_enc->autorefresh.kickoff_cnt), - phys_enc->frame_trigger_mode); + phys_enc->frame_trigger_mode, phys_enc->cont_splash_enabled); if (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_DEFAULT) { /* @@ -1473,6 +1497,9 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( } } + if (phys_enc->cont_splash_enabled) + _sde_encoder_phys_wait_for_vsync_on_autorefresh_busy(phys_enc); + if (phys_enc->recovered) { recovery_events = sde_encoder_recovery_events_enabled( phys_enc->parent); @@ -1965,6 +1992,7 @@ static void _sde_encoder_autorefresh_disable_seq2( tear_status.write_count); } } + static void _sde_encoder_phys_disable_autorefresh(struct sde_encoder_phys *phys_enc) { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); @@ -2129,6 +2157,8 @@ static void sde_encoder_phys_cmd_init_ops(struct sde_encoder_phys_ops *ops) ops->collect_misr = sde_encoder_helper_collect_misr; ops->add_to_minidump = sde_encoder_phys_cmd_add_enc_to_minidump; ops->disable_autorefresh = _sde_encoder_phys_disable_autorefresh; + ops->wait_for_vsync_on_autorefresh_busy = + _sde_encoder_phys_wait_for_vsync_on_autorefresh_busy; } static inline bool sde_encoder_phys_cmd_intf_te_supported(