From 18fe66c89efce127520432942681dfc62ec3f6ff Mon Sep 17 00:00:00 2001 From: Yashwanth Date: Fri, 28 Feb 2020 19:34:15 +0530 Subject: [PATCH 1/3] disp: msm: sde: reset crtc core perf while entering idle state After coming out of idle state, bus vote is governed only if there any change in perf compared to before entering idle state. If the perf is same before and after the idle state, bus update request is not considered and min bus votes are voted. This change resets crtc core perf while entering idle state always in command mode. Change-Id: If172207422adc25fcee497aebe23aad1ac6ce7cc Signed-off-by: Yashwanth --- msm/sde/sde_encoder.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index d6bc4cf32e4c..ff2865599ec7 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -1805,6 +1805,14 @@ end: static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc, u32 sw_event, struct sde_encoder_virt *sde_enc, bool is_vid_mode) { + struct msm_drm_private *priv; + struct sde_kms *sde_kms; + struct drm_crtc *crtc = drm_enc->crtc; + struct sde_crtc *sde_crtc = to_sde_crtc(crtc); + + priv = drm_enc->dev->dev_private; + sde_kms = to_sde_kms(priv->kms); + mutex_lock(&sde_enc->rc_lock); if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) { @@ -1829,6 +1837,10 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc, /* disable all the clks and resources */ _sde_encoder_update_rsc_client(drm_enc, false); _sde_encoder_resource_control_helper(drm_enc, false); + + if (!sde_kms->perf.bw_vote_mode) + memset(&sde_crtc->cur_perf, 0, + sizeof(struct sde_core_perf_params)); } SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, From d1965c6ca89f36a4c0eaf8d68e7f9f1fea0a1e20 Mon Sep 17 00:00:00 2001 From: Yashwanth Date: Mon, 2 Mar 2020 23:42:36 +0530 Subject: [PATCH 2/3] disp: msm: sde: add cb func check before enabling irq Acquiring mutex lock after enabling irq might lead to deadlock if irq is dispatched immediately in some cases. This change moves callback func check for irq prior to enabling the irq line. Change-Id: Ie1622e1ade268e41e97bf6d7683fa0bd972bcb7c Signed-off-by: Yashwanth --- msm/sde/sde_core_irq.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/msm/sde/sde_core_irq.c b/msm/sde/sde_core_irq.c index f2dc66fa6f59..5ee1865be632 100644 --- a/msm/sde/sde_core_irq.c +++ b/msm/sde/sde_core_irq.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ @@ -115,24 +115,26 @@ static int _sde_core_irq_enable(struct sde_kms *sde_kms, int irq_idx) SDE_EVT32(irq_idx, atomic_read(&sde_kms->irq_obj.enable_counts[irq_idx])); - spin_lock_irqsave(&sde_kms->hw_intr->irq_lock, irq_flags); - if (atomic_inc_return(&sde_kms->irq_obj.enable_counts[irq_idx]) == 1) + + if (atomic_inc_return(&sde_kms->irq_obj.enable_counts[irq_idx]) == 1) { + spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags); + /* empty callback list but interrupt is being enabled */ + if (list_empty(&sde_kms->irq_obj.irq_cb_tbl[irq_idx])) + SDE_ERROR("enabling irq_idx=%d with no callback\n", + irq_idx); + spin_unlock_irqrestore(&sde_kms->irq_obj.cb_lock, irq_flags); + + spin_lock_irqsave(&sde_kms->hw_intr->irq_lock, irq_flags); ret = sde_kms->hw_intr->ops.enable_irq_nolock( sde_kms->hw_intr, irq_idx); - spin_unlock_irqrestore(&sde_kms->hw_intr->irq_lock, irq_flags); + spin_unlock_irqrestore(&sde_kms->hw_intr->irq_lock, irq_flags); + } + if (ret) SDE_ERROR("Fail to enable IRQ for irq_idx:%d\n", irq_idx); SDE_DEBUG("irq_idx=%d ret=%d\n", irq_idx, ret); - if (atomic_read(&sde_kms->irq_obj.enable_counts[irq_idx]) == 1) { - spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags); - /* empty callback list but interrupt is enabled */ - if (list_empty(&sde_kms->irq_obj.irq_cb_tbl[irq_idx])) - SDE_ERROR("irq_idx=%d enabled with no callback\n", - irq_idx); - spin_unlock_irqrestore(&sde_kms->irq_obj.cb_lock, irq_flags); - } return ret; } From e32095527a34356f6086fa57e6a39e1dd624585c Mon Sep 17 00:00:00 2001 From: Jayaprakash Date: Tue, 17 Mar 2020 00:03:34 +0530 Subject: [PATCH 3/3] disp: msm: sde: avoid solver mode if autorefresh is enabled In dual display with continuous splash, when autorefresh gets disabled in primary on first commit, solver mode gets enabled and mdp_clock is gated whenever primary enters idle. The secondary data path will get gated during that time and not advance anymore. Asynchronous gating of the mdp_clock during operation can also hang the secondary path. This change avoids entering the solver mode which fixes the timeout in the autorefresh disable sequence in the secondary. Change-Id: I7562ce2ad72d3bb8e8b6b8f356fab6def0caaf92 Signed-off-by: Jayaprakash --- msm/sde/sde_encoder.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index ff2865599ec7..4c1e8e785878 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -1190,6 +1190,7 @@ static int _sde_encoder_update_rsc_client( u32 qsync_mode = 0, v_front_porch; struct drm_display_mode *mode; bool is_vid_mode; + struct drm_encoder *enc; if (!drm_enc || !drm_enc->dev) { SDE_ERROR("invalid encoder arguments\n"); @@ -1232,6 +1233,12 @@ static int _sde_encoder_update_rsc_client( else if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_VIDEO_MODE)) rsc_state = enable ? SDE_RSC_VID_STATE : SDE_RSC_IDLE_STATE; + drm_for_each_encoder(enc, drm_enc->dev) { + if (enc->base.id != drm_enc->base.id && + sde_encoder_in_cont_splash(enc)) + rsc_state = SDE_RSC_CLK_STATE; + } + SDE_EVT32(rsc_state, qsync_mode); is_vid_mode = sde_encoder_check_curr_mode(&sde_enc->base,