diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 9580f3159f..4e977940b9 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -3979,7 +3979,7 @@ int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state, continue; if (sde_encoder_get_intf_mode(encoder) == INTF_MODE_VIDEO) - sde_encoder_kickoff(encoder, false, true); + sde_encoder_kickoff(encoder, true); } /* panic the device if VBIF is not in good state */ @@ -4086,7 +4086,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; - sde_encoder_kickoff(encoder, false, true); + sde_encoder_kickoff(encoder, true); } sde_crtc->kickoff_in_progress = false; @@ -7061,7 +7061,7 @@ void __sde_crtc_static_cache_read_work(struct kthread_work *work) sde_plane_ctl_flush(plane, ctl, true); /* kickoff encoder and wait for VBLANK */ - sde_encoder_kickoff(drm_enc, false, false); + sde_encoder_kickoff(drm_enc, false); sde_encoder_wait_for_event(drm_enc, MSM_ENC_VBLANK); SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_EXIT); diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index eae48d797e..16ca653405 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -3225,6 +3225,19 @@ void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc, ctl->ops.clear_pending_flush(ctl); } +void sde_encoder_helper_phys_reset(struct sde_encoder_phys *phys_enc) +{ + struct sde_hw_ctl *ctl = phys_enc->hw_ctl; + struct sde_ctl_flush_cfg cfg; + + ctl->ops.reset(ctl); + sde_encoder_helper_reset_mixers(phys_enc, NULL); + ctl->ops.get_pending_flush(ctl, &cfg); + SDE_EVT32(DRMID(phys_enc->parent), cfg.pending_flush_mask); + ctl->ops.trigger_flush(ctl); + ctl->ops.trigger_start(ctl); +} + static enum sde_intf sde_encoder_get_intf(struct sde_mdss_cfg *catalog, enum sde_intf_type type, u32 controller_id) { @@ -4357,47 +4370,7 @@ end: return ret; } -/** - * _sde_encoder_reset_ctl_hw - reset h/w configuration for all ctl's associated - * with the specified encoder, and unstage all pipes from it - * @encoder: encoder pointer - * Returns: 0 on success - */ -static int _sde_encoder_reset_ctl_hw(struct drm_encoder *drm_enc) -{ - struct sde_encoder_virt *sde_enc; - struct sde_encoder_phys *phys; - unsigned int i; - int rc = 0; - - if (!drm_enc) { - SDE_ERROR("invalid encoder\n"); - return -EINVAL; - } - - sde_enc = to_sde_encoder_virt(drm_enc); - - SDE_ATRACE_BEGIN("encoder_release_lm"); - SDE_DEBUG_ENC(sde_enc, "\n"); - - for (i = 0; i < sde_enc->num_phys_encs; i++) { - phys = sde_enc->phys_encs[i]; - if (!phys) - continue; - - SDE_EVT32(DRMID(drm_enc), phys->intf_idx - INTF_0); - - rc = sde_encoder_helper_reset_mixers(phys, NULL); - if (rc) - SDE_EVT32(DRMID(drm_enc), rc, SDE_EVTLOG_ERROR); - } - - SDE_ATRACE_END("encoder_release_lm"); - return rc; -} - -void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool is_error, - bool config_changed) +void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool config_changed) { struct sde_encoder_virt *sde_enc; struct sde_encoder_phys *phys; @@ -4412,10 +4385,6 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool is_error, SDE_DEBUG_ENC(sde_enc, "\n"); - /* create a 'no pipes' commit to release buffers on errors */ - if (is_error) - _sde_encoder_reset_ctl_hw(drm_enc); - if (sde_enc->delay_kickoff) { u32 loop_count = 20; u32 sleep = DELAY_KICKOFF_POLL_TIMEOUT_US / loop_count; diff --git a/msm/sde/sde_encoder.h b/msm/sde/sde_encoder.h index b253377c04..6c7604a837 100644 --- a/msm/sde/sde_encoder.h +++ b/msm/sde/sde_encoder.h @@ -325,12 +325,9 @@ void sde_encoder_trigger_kickoff_pending(struct drm_encoder *encoder); * sde_encoder_kickoff - trigger a double buffer flip of the ctl path * (i.e. ctl flush and start) immediately. * @encoder: encoder pointer - * @is_error: whether the current commit needs to be aborted and replaced - * with a 'safe' commit * @config_changed: if true new configuration is applied on the control path */ -void sde_encoder_kickoff(struct drm_encoder *encoder, bool is_error, - bool config_changed); +void sde_encoder_kickoff(struct drm_encoder *encoder, bool config_changed); /** * sde_encoder_wait_for_event - Waits for encoder events diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index 94e813e53a..740b649684 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/msm/sde/sde_encoder_phys.h @@ -804,6 +804,13 @@ static inline bool sde_encoder_phys_needs_single_flush( void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc, struct sde_encoder_phys_wb *wb_enc); +/** + * sde_encoder_helper_phys_reset - helper function to reset virt encoder + * if vsync is missing on phys encoder + * @phys_enc: Pointer to physical encoder structure + */ +void sde_encoder_helper_phys_reset(struct sde_encoder_phys *phys_enc); + /** * sde_encoder_helper_setup_misr - helper function to setup misr * @phys_enc: Pointer to physical encoder structure diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index c854703965..d8a800c353 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/msm/sde/sde_encoder_phys_vid.c @@ -920,6 +920,18 @@ static int sde_encoder_phys_vid_wait_for_vblank( return _sde_encoder_phys_vid_wait_for_vblank(phys_enc, true); } +static int sde_encoder_phys_vid_wait_for_commit_done( + struct sde_encoder_phys *phys_enc) +{ + int rc; + + rc = _sde_encoder_phys_vid_wait_for_vblank(phys_enc, true); + if (rc) + sde_encoder_helper_phys_reset(phys_enc); + + return rc; +} + static int sde_encoder_phys_vid_wait_for_vblank_no_notify( struct sde_encoder_phys *phys_enc) { @@ -1310,7 +1322,7 @@ static void sde_encoder_phys_vid_init_ops(struct sde_encoder_phys_ops *ops) ops->destroy = sde_encoder_phys_vid_destroy; ops->get_hw_resources = sde_encoder_phys_vid_get_hw_resources; ops->control_vblank_irq = sde_encoder_phys_vid_control_vblank_irq; - ops->wait_for_commit_done = sde_encoder_phys_vid_wait_for_vblank; + ops->wait_for_commit_done = sde_encoder_phys_vid_wait_for_commit_done; ops->wait_for_vblank = sde_encoder_phys_vid_wait_for_vblank_no_notify; ops->wait_for_tx_complete = sde_encoder_phys_vid_wait_for_vblank; ops->irq_control = sde_encoder_phys_vid_irq_control;