From 8b01e6124e7b411ee5f26968f1a3546212672c5c Mon Sep 17 00:00:00 2001 From: Jayaprakash Madisetty Date: Fri, 3 Dec 2021 13:17:08 +0530 Subject: [PATCH] disp: msm: sde: reset mixers in crtc when ctl datapath switches This change reinitializes the sde_crtc->mixers when CTL datapath switch occurs during mode set and RM allocation of CTL hw block is changed. This initialization is required for CTL_LAYER programming to trigger on the new CTL allocated from RM. Issue case: 1. Primary Display is using CTL_0 and it is reserved. 2. Secondary Display is using CTL_1. On suspend, RM adds CTL_1 into the free list. 3. External Display is powered on, RM allocates CTL_1 hw blk. 4. Secondary Display is powered on, RM allocated CTL_2 hw blk. 5. External Display is suspended/unplugged, RM adds CTL_1 into the free list. 6. When any mode_set(say fps switch) occurs on secondary, RM allocates new resources and CTL_1 is allocated. sde_crtc->num_mixers is non zero, so all the layer programming happens on CTL_2, but CTL_1_FLUSH bits are programmed causing hw timeout issue. Change-Id: I5f1f52b7673740c48b249ab4d36e80b7a1d3db96 Signed-off-by: Jayaprakash Madisetty --- msm/sde/sde_crtc.c | 4 ++++ msm/sde/sde_crtc.h | 3 +++ msm/sde/sde_encoder.c | 6 +++++- msm/sde/sde_encoder_phys.h | 3 ++- msm/sde/sde_encoder_phys_cmd.c | 11 +++++++++-- msm/sde/sde_encoder_phys_vid.c | 11 +++++++++-- msm/sde/sde_encoder_phys_wb.c | 11 +++++++++-- 7 files changed, 41 insertions(+), 8 deletions(-) diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 55c93c2eb2..7652b2739e 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -3578,6 +3579,9 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, _sde_crtc_setup_is_ppsplit(crtc->state); _sde_crtc_setup_lm_bounds(crtc, crtc->state); _sde_crtc_clear_all_blend_stages(sde_crtc); + } else if (sde_crtc->num_mixers && sde_crtc->reinit_crtc_mixers) { + _sde_crtc_setup_mixers(crtc); + sde_crtc->reinit_crtc_mixers = false; } list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index 6ea3d62ef7..4fb361d12b 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -316,6 +317,7 @@ struct sde_frame_data { * @ltm_buffer_lock : muttx to protect ltm_buffers allcation and free * @ltm_lock : Spinlock to protect ltm buffer_cnt, hist_en and ltm lists * @needs_hw_reset : Initiate a hw ctl reset + * @reinit_crtc_mixers : Reinitialize mixers in crtc * @hist_irq_idx : hist interrupt irq idx * @disable_pending_cp : flag tracks pending color processing features force disable * @src_bpp : source bpp used to calculate compression ratio @@ -415,6 +417,7 @@ struct sde_crtc { struct mutex ltm_buffer_lock; spinlock_t ltm_lock; bool needs_hw_reset; + bool reinit_crtc_mixers; int hist_irq_idx; bool disable_pending_cp; diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index d6a35dcfd8..94dee66315 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -2487,6 +2488,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct drm_connector *conn; struct sde_connector_state *c_state; struct msm_display_mode *msm_mode; + struct sde_crtc *sde_crtc; int i = 0, ret; int num_lm, num_intf, num_pp_per_intf; @@ -2518,6 +2520,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, } sde_enc->crtc = drm_enc->crtc; + sde_crtc = to_sde_crtc(drm_enc->crtc); sde_crtc_set_qos_dirty(drm_enc->crtc); /* get and store the mode_info */ @@ -2577,7 +2580,8 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, phys->hw_pp = sde_enc->hw_pp[i * num_pp_per_intf]; phys->connector = conn; if (phys->ops.mode_set) - phys->ops.mode_set(phys, mode, adj_mode); + phys->ops.mode_set(phys, mode, adj_mode, + &sde_crtc->reinit_crtc_mixers); } } diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index 740b649684..353e47e570 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/msm/sde/sde_encoder_phys.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -146,7 +147,7 @@ struct sde_encoder_phys_ops { struct drm_display_mode *adjusted_mode); void (*mode_set)(struct sde_encoder_phys *encoder, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); + struct drm_display_mode *adjusted_mode, bool *reinit_mixers); void (*cont_splash_mode_set)(struct sde_encoder_phys *encoder, struct drm_display_mode *adjusted_mode); void (*enable)(struct sde_encoder_phys *encoder); diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index d48957508c..29b9005ad7 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -406,7 +407,7 @@ static void sde_encoder_phys_cmd_cont_splash_mode_set( static void sde_encoder_phys_cmd_mode_set( struct sde_encoder_phys *phys_enc, struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) + struct drm_display_mode *adj_mode, bool *reinit_mixers) { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); @@ -427,8 +428,14 @@ static void sde_encoder_phys_cmd_mode_set( /* Retrieve previously allocated HW Resources. Shouldn't fail */ sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL); for (i = 0; i <= instance; i++) { - if (sde_rm_get_hw(rm, &iter)) + if (sde_rm_get_hw(rm, &iter)) { + if (phys_enc->hw_ctl && phys_enc->hw_ctl != iter.hw) { + *reinit_mixers = true; + SDE_EVT32(phys_enc->hw_ctl->idx, + ((struct sde_hw_ctl *)iter.hw)->idx); + } phys_enc->hw_ctl = (struct sde_hw_ctl *)iter.hw; + } } if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) { diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index d8a800c353..90d9dc608f 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/msm/sde/sde_encoder_phys_vid.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -606,7 +607,7 @@ static void sde_encoder_phys_vid_cont_splash_mode_set( static void sde_encoder_phys_vid_mode_set( struct sde_encoder_phys *phys_enc, struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) + struct drm_display_mode *adj_mode, bool *reinit_mixers) { struct sde_rm *rm; struct sde_rm_hw_iter iter; @@ -632,8 +633,14 @@ static void sde_encoder_phys_vid_mode_set( /* Retrieve previously allocated HW Resources. Shouldn't fail */ sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL); for (i = 0; i <= instance; i++) { - if (sde_rm_get_hw(rm, &iter)) + if (sde_rm_get_hw(rm, &iter)) { + if (phys_enc->hw_ctl && phys_enc->hw_ctl != iter.hw) { + *reinit_mixers = true; + SDE_EVT32(phys_enc->hw_ctl->idx, + ((struct sde_hw_ctl *)iter.hw)->idx); + } phys_enc->hw_ctl = (struct sde_hw_ctl *)iter.hw; + } } if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) { SDE_ERROR_VIDENC(vid_enc, "failed to init ctl, %ld\n", diff --git a/msm/sde/sde_encoder_phys_wb.c b/msm/sde/sde_encoder_phys_wb.c index 9ac21bab89..15e16048aa 100644 --- a/msm/sde/sde_encoder_phys_wb.c +++ b/msm/sde/sde_encoder_phys_wb.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -1355,7 +1356,7 @@ static void sde_encoder_phys_wb_irq_ctrl( static void sde_encoder_phys_wb_mode_set( struct sde_encoder_phys *phys_enc, struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) + struct drm_display_mode *adj_mode, bool *reinit_mixers) { struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); struct sde_rm *rm = &phys_enc->sde_kms->rm; @@ -1377,8 +1378,14 @@ static void sde_encoder_phys_wb_mode_set( sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL); for (i = 0; i <= instance; i++) { sde_rm_get_hw(rm, &iter); - if (i == instance) + if (i == instance) { + if (phys_enc->hw_ctl && phys_enc->hw_ctl != iter.hw) { + *reinit_mixers = true; + SDE_EVT32(phys_enc->hw_ctl->idx, + ((struct sde_hw_ctl *)iter.hw)->idx); + } phys_enc->hw_ctl = (struct sde_hw_ctl *) iter.hw; + } } if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) {