From ae98505aae5c777a7397d08098f7d6c309eaecc6 Mon Sep 17 00:00:00 2001 From: Mahadevan Date: Fri, 13 Aug 2021 20:18:01 +0530 Subject: [PATCH] disp: msm: sde: switch rsc state before CTL_PREPARE in dual display In dual display usecase when both displays comes out of idle following scenario will cause wr_ptr timeout. 1. Both displays goes to idle and RSCC enters Mode-2. 2. Primary display exit idle upon DRM commit N RSC enters Solver State. 3. Secondary display exits idle upon DRM commit M and waits on input fence after CTL_1_PREPARE is set. RSC is still in CMD state. 4. Primary Commit N frame transfer got successful and commit N+1 is queued in primary display when RSC in solver state which leads to timeout in primary. This is because RSCC will not generate a wakeup in sync with primary timelines leading to timeout. This is because RSCC still sees idle low thinking frame transfer is taking long time. This change will switch the rsc state to AMC mode before CTL_PREPARE is set which resolves such issue. Change-Id: Ic32e48b4febbbcc54d94876194d38fe6ef3d0981 Signed-off-by: Mahadevan --- msm/sde/sde_crtc.c | 1 + msm/sde/sde_encoder.c | 40 ++++++++++++++++++++++++++++++++++++++++ msm/sde/sde_encoder.h | 6 ++++++ 3 files changed, 47 insertions(+) diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 260e713c34d2..2c08ab9b2e5e 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -3298,6 +3298,7 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; + sde_encoder_trigger_rsc_state_change(encoder); /* encoder will trigger pending mask now */ sde_encoder_trigger_kickoff_pending(encoder); } diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index cb5990cd52bb..7f1a99b5f53b 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -3797,6 +3797,46 @@ bool sde_encoder_check_curr_mode(struct drm_encoder *drm_enc, u32 mode) return (disp_info->curr_panel_mode == mode); } +void sde_encoder_trigger_rsc_state_change(struct drm_encoder *drm_enc) +{ + struct sde_encoder_virt *sde_enc = NULL; + int ret = 0; + + sde_enc = to_sde_encoder_virt(drm_enc); + + if (!sde_enc) + return; + + mutex_lock(&sde_enc->rc_lock); + /* + * In dual display case when secondary comes out of + * idle make sure RSC solver mode is disabled before + * setting CTL_PREPARE. + */ + if (!sde_enc->cur_master || + !sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE) || + sde_enc->disp_info.display_type == SDE_CONNECTOR_PRIMARY || + sde_enc->rc_state != SDE_ENC_RC_STATE_IDLE) + goto end; + + /* enable all the clks and resources */ + ret = _sde_encoder_resource_control_helper(drm_enc, true); + if (ret) { + SDE_ERROR_ENC(sde_enc, "rc in state %d\n", sde_enc->rc_state); + SDE_EVT32(DRMID(drm_enc), sde_enc->rc_state, SDE_EVTLOG_ERROR); + goto end; + } + + _sde_encoder_update_rsc_client(drm_enc, true); + + SDE_EVT32(DRMID(drm_enc), sde_enc->rc_state, SDE_ENC_RC_STATE_ON); + sde_enc->rc_state = SDE_ENC_RC_STATE_ON; + +end: + mutex_unlock(&sde_enc->rc_lock); +} + + void sde_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc; diff --git a/msm/sde/sde_encoder.h b/msm/sde/sde_encoder.h index 8e90c1408483..27116034c11b 100644 --- a/msm/sde/sde_encoder.h +++ b/msm/sde/sde_encoder.h @@ -275,6 +275,12 @@ void sde_encoder_get_hw_resources(struct drm_encoder *encoder, struct sde_encoder_hw_resources *hw_res, struct drm_connector_state *conn_state); +/** + * sde_encoder_trigger_rsc_state_change - rsc state change. + * @encoder: encoder pointer + */ +void sde_encoder_trigger_rsc_state_change(struct drm_encoder *drm_enc); + /** * sde_encoder_early_wakeup - early wake up display * @encoder: encoder pointer