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 <quic_jmadiset@quicinc.com>
This commit is contained in:
Jayaprakash Madisetty
2021-12-03 13:17:08 +05:30
parent 2a867bb340
commit 8b01e6124e
7 changed files with 41 additions and 8 deletions

View File

@@ -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) 2014-2021 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat * Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com> * Author: Rob Clark <robdclark@gmail.com>
@@ -3578,6 +3579,9 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
_sde_crtc_setup_is_ppsplit(crtc->state); _sde_crtc_setup_is_ppsplit(crtc->state);
_sde_crtc_setup_lm_bounds(crtc, crtc->state); _sde_crtc_setup_lm_bounds(crtc, crtc->state);
_sde_crtc_clear_all_blend_stages(sde_crtc); _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) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {

View File

@@ -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) 2015-2021 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat * Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com> * Author: Rob Clark <robdclark@gmail.com>
@@ -316,6 +317,7 @@ struct sde_frame_data {
* @ltm_buffer_lock : muttx to protect ltm_buffers allcation and free * @ltm_buffer_lock : muttx to protect ltm_buffers allcation and free
* @ltm_lock : Spinlock to protect ltm buffer_cnt, hist_en and ltm lists * @ltm_lock : Spinlock to protect ltm buffer_cnt, hist_en and ltm lists
* @needs_hw_reset : Initiate a hw ctl reset * @needs_hw_reset : Initiate a hw ctl reset
* @reinit_crtc_mixers : Reinitialize mixers in crtc
* @hist_irq_idx : hist interrupt irq idx * @hist_irq_idx : hist interrupt irq idx
* @disable_pending_cp : flag tracks pending color processing features force disable * @disable_pending_cp : flag tracks pending color processing features force disable
* @src_bpp : source bpp used to calculate compression ratio * @src_bpp : source bpp used to calculate compression ratio
@@ -415,6 +417,7 @@ struct sde_crtc {
struct mutex ltm_buffer_lock; struct mutex ltm_buffer_lock;
spinlock_t ltm_lock; spinlock_t ltm_lock;
bool needs_hw_reset; bool needs_hw_reset;
bool reinit_crtc_mixers;
int hist_irq_idx; int hist_irq_idx;
bool disable_pending_cp; bool disable_pending_cp;

View File

@@ -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) 2014-2021, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat * Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com> * Author: Rob Clark <robdclark@gmail.com>
@@ -2487,6 +2488,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
struct drm_connector *conn; struct drm_connector *conn;
struct sde_connector_state *c_state; struct sde_connector_state *c_state;
struct msm_display_mode *msm_mode; struct msm_display_mode *msm_mode;
struct sde_crtc *sde_crtc;
int i = 0, ret; int i = 0, ret;
int num_lm, num_intf, num_pp_per_intf; 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_enc->crtc = drm_enc->crtc;
sde_crtc = to_sde_crtc(drm_enc->crtc);
sde_crtc_set_qos_dirty(drm_enc->crtc); sde_crtc_set_qos_dirty(drm_enc->crtc);
/* get and store the mode_info */ /* 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->hw_pp = sde_enc->hw_pp[i * num_pp_per_intf];
phys->connector = conn; phys->connector = conn;
if (phys->ops.mode_set) 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);
} }
} }

View File

@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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. * 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); struct drm_display_mode *adjusted_mode);
void (*mode_set)(struct sde_encoder_phys *encoder, void (*mode_set)(struct sde_encoder_phys *encoder,
struct drm_display_mode *mode, 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, void (*cont_splash_mode_set)(struct sde_encoder_phys *encoder,
struct drm_display_mode *adjusted_mode); struct drm_display_mode *adjusted_mode);
void (*enable)(struct sde_encoder_phys *encoder); void (*enable)(struct sde_encoder_phys *encoder);

View File

@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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. * 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( static void sde_encoder_phys_cmd_mode_set(
struct sde_encoder_phys *phys_enc, struct sde_encoder_phys *phys_enc,
struct drm_display_mode *mode, 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 = struct sde_encoder_phys_cmd *cmd_enc =
to_sde_encoder_phys_cmd(phys_enc); to_sde_encoder_phys_cmd(phys_enc);
@@ -427,9 +428,15 @@ static void sde_encoder_phys_cmd_mode_set(
/* Retrieve previously allocated HW Resources. Shouldn't fail */ /* Retrieve previously allocated HW Resources. Shouldn't fail */
sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL); sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL);
for (i = 0; i <= instance; i++) { 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; phys_enc->hw_ctl = (struct sde_hw_ctl *)iter.hw;
} }
}
if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) { if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) {
SDE_ERROR_CMDENC(cmd_enc, "failed to init ctl: %ld\n", SDE_ERROR_CMDENC(cmd_enc, "failed to init ctl: %ld\n",

View File

@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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. * 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( static void sde_encoder_phys_vid_mode_set(
struct sde_encoder_phys *phys_enc, struct sde_encoder_phys *phys_enc,
struct drm_display_mode *mode, 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 *rm;
struct sde_rm_hw_iter iter; struct sde_rm_hw_iter iter;
@@ -632,9 +633,15 @@ static void sde_encoder_phys_vid_mode_set(
/* Retrieve previously allocated HW Resources. Shouldn't fail */ /* Retrieve previously allocated HW Resources. Shouldn't fail */
sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL); sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL);
for (i = 0; i <= instance; i++) { 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; phys_enc->hw_ctl = (struct sde_hw_ctl *)iter.hw;
} }
}
if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) { if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) {
SDE_ERROR_VIDENC(vid_enc, "failed to init ctl, %ld\n", SDE_ERROR_VIDENC(vid_enc, "failed to init ctl, %ld\n",
PTR_ERR(phys_enc->hw_ctl)); PTR_ERR(phys_enc->hw_ctl));

View File

@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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. * 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( static void sde_encoder_phys_wb_mode_set(
struct sde_encoder_phys *phys_enc, struct sde_encoder_phys *phys_enc,
struct drm_display_mode *mode, 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_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
struct sde_rm *rm = &phys_enc->sde_kms->rm; struct sde_rm *rm = &phys_enc->sde_kms->rm;
@@ -1377,9 +1378,15 @@ static void sde_encoder_phys_wb_mode_set(
sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL); sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL);
for (i = 0; i <= instance; i++) { for (i = 0; i <= instance; i++) {
sde_rm_get_hw(rm, &iter); 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; phys_enc->hw_ctl = (struct sde_hw_ctl *) iter.hw;
} }
}
if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) { if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) {
SDE_ERROR("failed init ctl: %ld\n", SDE_ERROR("failed init ctl: %ld\n",