From: Xi Zhang <[email protected]> dpu_encoder_helper_reset_mixers, which is called during atomic_commit disable phase, previously called dpu_kms_get_existing_global_state, which returns the global_state after the state swap. So the cleanup was performed on the newly allocated resources instead of the ones that actually need reset.
Cache LMs in dpu_enc similar to other resources during mode set, and perform the cleanup on cached LMs instead. Also removed redundant ctl->ops.setup_blendstage during cleanup since ctl->ops.clear_all_blendstages covers it already. Signed-off-by: Xi Zhang <[email protected]> --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 57 +++++++++++++++-------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 8d2b4d2726f2..09afc0681248 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -133,6 +133,7 @@ enum dpu_enc_rc_states { * @cur_master: Pointer to the current master in this mode. Optimization * Only valid after enable. Cleared as disable. * @cur_slave: As above but for the slave encoder. + * @hw_mixer: Handle to the layer mixers used for the display. * @hw_pp: Handle to the pingpong blocks used for the display. No. * pingpong blocks can be different than num_phys_encs. * @hw_cwb: Handle to the CWB muxes used for concurrent writeback @@ -182,6 +183,7 @@ struct dpu_encoder_virt { struct dpu_encoder_phys *phys_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL]; struct dpu_encoder_phys *cur_master; struct dpu_encoder_phys *cur_slave; + struct dpu_hw_mixer *hw_mixer[MAX_CHANNELS_PER_ENC]; struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC]; struct dpu_hw_cwb *hw_cwb[MAX_CWB_PER_ENC]; struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; @@ -1156,11 +1158,12 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, struct msm_drm_private *priv; struct dpu_kms *dpu_kms; struct dpu_global_state *global_state; + struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC]; - int num_ctl, num_pp, num_dsc, num_pp_per_intf; + int num_ctl, num_lm, num_pp, num_dsc, num_pp_per_intf; int num_cwb = 0; bool is_cwb_encoder; unsigned int dsc_mask = 0; @@ -1189,6 +1192,14 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, trace_dpu_enc_mode_set(DRMID(drm_enc)); /* Query resource that have been reserved in atomic check step. */ + + num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, + drm_enc->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm)); + + for (i = 0; i < ARRAY_SIZE(dpu_enc->hw_mixer); i++) + dpu_enc->hw_mixer[i] = i < num_lm ? to_dpu_hw_mixer(hw_lm[i]) + : NULL; + if (is_cwb_encoder) { num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, drm_enc->crtc, @@ -2183,42 +2194,34 @@ void dpu_encoder_kickoff(struct drm_encoder *drm_enc) static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc) { - int i, num_lm; - struct dpu_global_state *global_state; - struct dpu_hw_blk *hw_lm[2]; - struct dpu_hw_mixer *hw_mixer[2]; + int i; struct dpu_hw_ctl *ctl = phys_enc->hw_ctl; + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(phys_enc->parent); /* reset all mixers for this encoder */ if (ctl->ops.clear_all_blendstages) ctl->ops.clear_all_blendstages(ctl); - global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms); + for (i = 0; i < ARRAY_SIZE(dpu_enc->hw_mixer); i++) { + if (dpu_enc->hw_mixer[i]) { + if (ctl->ops.update_pending_flush_mixer) + ctl->ops.update_pending_flush_mixer(ctl, dpu_enc->hw_mixer[i]->idx); - num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state, - phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm)); - - for (i = 0; i < num_lm; i++) { - hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]); - if (ctl->ops.update_pending_flush_mixer) - ctl->ops.update_pending_flush_mixer(ctl, hw_mixer[i]->idx); - - /* clear all blendstages */ - if (ctl->ops.setup_blendstage) - ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL); - - if (hw_mixer[i]->ops.clear_all_blendstages) - hw_mixer[i]->ops.clear_all_blendstages(hw_mixer[i]); + /* clear all blendstages */ + if (dpu_enc->hw_mixer[i]->ops.clear_all_blendstages) + dpu_enc->hw_mixer[i]->ops.clear_all_blendstages( + dpu_enc->hw_mixer[i]); + } + } - if (ctl->ops.set_active_lms) - ctl->ops.set_active_lms(ctl, NULL); + if (ctl->ops.set_active_lms) + ctl->ops.set_active_lms(ctl, NULL); - if (ctl->ops.set_active_fetch_pipes) - ctl->ops.set_active_fetch_pipes(ctl, NULL); + if (ctl->ops.set_active_fetch_pipes) + ctl->ops.set_active_fetch_pipes(ctl, NULL); - if (ctl->ops.set_active_pipes) - ctl->ops.set_active_pipes(ctl, NULL); - } + if (ctl->ops.set_active_pipes) + ctl->ops.set_active_pipes(ctl, NULL); } static void dpu_encoder_dsc_pipe_clr(struct dpu_hw_ctl *ctl, -- 2.55.0
