From 902ca46c21a2b4672d1714390e86a025e6fe6f09 Mon Sep 17 00:00:00 2001 From: Mahadevan Date: Tue, 28 Feb 2023 13:15:07 +0530 Subject: [PATCH 01/12] Revert "disp: msm: sde: update idlepc handling for wfd display" This reverts commit a5b326dc2d7b0af94099c08cf9d06e5b50de52ad. Change-Id: Ib2c4bd379807047bc5bc4dc8ebb8ec2dddfa45be Signed-off-by: Mahadevan --- msm/sde/sde_crtc.c | 10 ++++++++++ msm/sde/sde_crtc.h | 10 ---------- msm/sde/sde_encoder.c | 6 +----- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 56ae133b..b3f88239 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -6665,6 +6665,16 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc, vfree(info); } +static bool _is_crtc_intf_mode_wb(struct drm_crtc *crtc) +{ + enum sde_intf_mode intf_mode = sde_crtc_get_intf_mode(crtc, crtc->state); + + if ((intf_mode != INTF_MODE_WB_BLOCK) && (intf_mode != INTF_MODE_WB_LINE)) + return false; + + return true; +} + static int _sde_crtc_get_output_fence(struct drm_crtc *crtc, const struct drm_crtc_state *state, uint64_t *val) { diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index 18d7efe8..8294bc45 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -957,16 +957,6 @@ static inline bool sde_crtc_state_in_clone_mode(struct drm_encoder *encoder, return false; } -static inline bool _is_crtc_intf_mode_wb(struct drm_crtc *crtc) -{ - enum sde_intf_mode intf_mode = sde_crtc_get_intf_mode(crtc, crtc->state); - - if ((intf_mode != INTF_MODE_WB_BLOCK) && (intf_mode != INTF_MODE_WB_LINE)) - return false; - - return true; -} - /** * sde_crtc_get_ds_io_res - populates the destination scaler src/dst w/h * @state: pointer to drm crtc state diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index b06ffe37..76bf10c0 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -2301,11 +2301,7 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc, } crtc_id = drm_crtc_index(crtc); - /** - * Avoid power collapse entry for writeback crtc since HAL does not repopulate - * crtc, plane properties like luts for idlepc exit commit. - */ - if (is_vid_mode || _is_crtc_intf_mode_wb(crtc)) { + if (is_vid_mode) { sde_encoder_irq_control(drm_enc, false); _sde_encoder_pm_qos_remove_request(drm_enc); } else { From f349b4b629c67a603f0b36857fae49b6e876d809 Mon Sep 17 00:00:00 2001 From: Mahadevan Date: Tue, 28 Feb 2023 13:36:51 +0530 Subject: [PATCH 02/12] disp: msm: sde: avoid idlepc power collapse for wfd display When wfd display is connected, qseed3 coefficient lut programming is getting erased due to idle pc entry for wfd pipes. On idlepc exit commit, plane properties are not reconfigured from userspace since support is not present for writeback crtc. This patch updates idle pc handling to avoid gdsc power off when writeback crtc is connected and for CWB encoder gdsc power off will happen on idle pc entry. Change-Id: I5dbab75bdc647b8f3c2a23cbb4e9d82239fe533d Signed-off-by: Mahadevan --- msm/sde/sde_encoder.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 76bf10c0..aa72982e 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -2301,6 +2301,11 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc, } crtc_id = drm_crtc_index(crtc); + /* + * Avoid power collapse entry for writeback crtc since HAL does not repopulate + * crtc, plane properties like luts for idlepc exit commit. Here is_vid_mode will + * represents video mode panels and wfd baring CWB. + */ if (is_vid_mode) { sde_encoder_irq_control(drm_enc, false); _sde_encoder_pm_qos_remove_request(drm_enc); @@ -2419,8 +2424,10 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, } sde_enc = to_sde_encoder_virt(drm_enc); priv = drm_enc->dev->dev_private; - if (sde_encoder_check_curr_mode(&sde_enc->base, MSM_DISPLAY_VIDEO_MODE)) - is_vid_mode = true; + + /* is_vid_mode represents vid mode panel and WFD for clocks and irq control. */ + is_vid_mode = !((sde_encoder_get_intf_mode(drm_enc) == INTF_MODE_CMD) || + sde_encoder_in_clone_mode(drm_enc)); /* * when idle_pc is not supported, process only KICKOFF, STOP and MODESET * events and return early for other events (ie wb display). From bb2f14fff0a973a040aa6590a3bc7f01b0d21d31 Mon Sep 17 00:00:00 2001 From: Gaurav LNU Date: Sun, 12 Mar 2023 23:18:27 -0700 Subject: [PATCH 03/12] disp: msm: sde: increase buf array size This change increases the buf array size to accommodate all the characters as the buf array will store each digit of bit and enable as a char. Bit and enable variables are uint32 which could have max value of 2^32(10 digit), each digit of both variable will be stored as a char in buf (char)array. Change-Id: Iab6fcddc425642a29c6c0a59884121e328707465 Signed-off-by: Gaurav LNU --- msm/sde/sde_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 56ae133b..1029e705 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -7208,7 +7208,7 @@ static ssize_t _sde_debugfs_hw_fence_features_mask_wr(struct file *file, { struct sde_crtc *sde_crtc; u32 bit, enable; - char buf[10]; + char buf[25]; if (!file || !file->private_data) return -EINVAL; From 53bfeabc6d9c4624bfd045f4e33e5187f033339c Mon Sep 17 00:00:00 2001 From: Ayushi Makhija Date: Tue, 14 Feb 2023 12:48:02 +0530 Subject: [PATCH 04/12] disp: msm: dsi: improve logs for dual display case Improve logs for dual display case to differentiate between primary and secondary display. Change-Id: I8947ddcdce3f75095f4d74143ef8256ed5dd5b7d Signed-off-by: Ayushi Makhija --- msm/dsi/dsi_clk_manager.c | 4 +++- msm/dsi/dsi_display.c | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/msm/dsi/dsi_clk_manager.c b/msm/dsi/dsi_clk_manager.c index cd853398..e52465ff 100644 --- a/msm/dsi/dsi_clk_manager.c +++ b/msm/dsi/dsi_clk_manager.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -1214,7 +1215,8 @@ int dsi_clk_req_state(void *client, enum dsi_clk_type clk, if (changed) { rc = dsi_recheck_clk_state(mngr); if (rc) - DSI_ERR("Failed to adjust clock state rc = %d\n", rc); + DSI_ERR("[%s]%s: failed to adjust clock state rc = %d\n", + mngr->name, c->name, rc); } mutex_unlock(&mngr->clk_mutex); diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index e29ea0d7..16a27aaa 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -5279,7 +5279,7 @@ static int _dsi_display_dev_init(struct dsi_display *display) rc = dsi_display_res_init(display); if (rc) { DSI_ERR("[%s] failed to initialize resources, rc=%d\n", - display->name, rc); + display->name, rc); goto error; } error: @@ -5896,7 +5896,7 @@ static int dsi_display_init(struct dsi_display *display) rc = _dsi_display_dev_init(display); if (rc) { - DSI_ERR("device init failed, rc=%d\n", rc); + DSI_ERR("device init failed for %s, rc=%d\n", display->display_type, rc); goto end; } From 2c2f2d34480d25887a441e6b08a3f127542b14b9 Mon Sep 17 00:00:00 2001 From: Jayaprakash Madisetty Date: Mon, 28 Mar 2022 15:46:50 +0530 Subject: [PATCH 05/12] disp: msm: sde: add input handler unregister check before encoder wakeup During PM suspend in dual display usecase, the power off commit to turn off primary and secondary crtcs is done with only one drm_atomic_state scheduled on primary crtc_commit thread. At the same, touch events can happen on secondary panel, which will run input_event_work and schedule the sde_enc->delayed_off_work to turn off its enabled resources. There can be race between primary crtc_commit thread which unregisters input_event, cancels all the pending works before setting sde_enc->cur_master to NULL and input_event_work_handler which schedules the delayed_off_work without checking the input_event_handler state. This change adds input handler unregister check before triggering _sde_encoder_rc_early_wakeup. Change-Id: I553843f81078810784f18e92347f918ab6e4a9fe Signed-off-by: Jayaprakash Madisetty --- msm/sde/sde_encoder.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index b06ffe37..e91cade6 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -2272,11 +2272,18 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc, 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); + struct sde_crtc *sde_crtc; struct sde_connector *sde_conn; int crtc_id = 0; priv = drm_enc->dev->dev_private; + + if (!crtc || !sde_enc->cur_master || !priv->kms) { + SDE_ERROR("invalid args crtc:%d master:%d\n", !crtc, !sde_enc->cur_master); + return -EINVAL; + } + + sde_crtc = to_sde_crtc(crtc); sde_kms = to_sde_kms(priv->kms); sde_conn = to_sde_connector(sde_enc->cur_master->connector); @@ -2336,7 +2343,7 @@ static int _sde_encoder_rc_early_wakeup(struct drm_encoder *drm_enc, { bool autorefresh_enabled = false; struct msm_drm_thread *disp_thread; - int ret = 0; + int ret = 0, idle_pc_duration = 0; if (!sde_enc->crtc || sde_enc->crtc->index >= ARRAY_SIZE(priv->disp_thread)) { @@ -2364,11 +2371,14 @@ static int _sde_encoder_rc_early_wakeup(struct drm_encoder *drm_enc, goto end; } - if (!sde_crtc_frame_pending(sde_enc->crtc)) + if (!sde_crtc_frame_pending(sde_enc->crtc)) { kthread_mod_delayed_work(&disp_thread->worker, &sde_enc->delayed_off_work, msecs_to_jiffies( IDLE_POWERCOLLAPSE_DURATION)); + idle_pc_duration = IDLE_POWERCOLLAPSE_DURATION; + } + } else if (sde_enc->rc_state == SDE_ENC_RC_STATE_IDLE) { /* enable all the clks and resources */ ret = _sde_encoder_resource_control_helper(drm_enc, @@ -2396,12 +2406,13 @@ static int _sde_encoder_rc_early_wakeup(struct drm_encoder *drm_enc, &sde_enc->delayed_off_work, msecs_to_jiffies( IDLE_POWERCOLLAPSE_IN_EARLY_WAKEUP)); + idle_pc_duration = IDLE_POWERCOLLAPSE_IN_EARLY_WAKEUP; sde_enc->rc_state = SDE_ENC_RC_STATE_ON; } - SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, - SDE_ENC_RC_STATE_ON, SDE_EVTLOG_FUNC_CASE8); + SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, SDE_ENC_RC_STATE_ON, + idle_pc_duration, SDE_EVTLOG_FUNC_CASE8); end: mutex_unlock(&sde_enc->rc_lock); @@ -4442,8 +4453,13 @@ static void sde_encoder_input_event_work_handler(struct kthread_work *work) struct sde_encoder_virt *sde_enc = container_of(work, struct sde_encoder_virt, input_event_work); - if (!sde_enc) { - SDE_ERROR("invalid sde encoder\n"); + if (!sde_enc || !sde_enc->input_handler) { + SDE_ERROR("invalid args sde encoder\n"); + return; + } + + if (!sde_enc->input_handler->private) { + SDE_DEBUG_ENC(sde_enc, "input handler is unregistered\n"); return; } From 131c0f8604c9ebdb02e32369ebd143ddc692f728 Mon Sep 17 00:00:00 2001 From: Soutrik Mukhopadhyay Date: Tue, 14 Mar 2023 15:51:22 +0530 Subject: [PATCH 06/12] disp: msm: dp: release vcpi slots for a modeset change for crtc state In MST atomic check function, allow to release vcpi slots for any case of changes in modes, active state or connectors for a crtc state. This reverts the commmit id 28cde80bd3666b6b339a21cac3d04b3b11c318b6. Change-Id: Ice13790f2e652b336619e1d78b42ddb708b4cb2e Signed-off-by: Soutrik Mukhopadhyay --- msm/dp/dp_mst_drm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/msm/dp/dp_mst_drm.c b/msm/dp/dp_mst_drm.c index 155008db..50c49abd 100644 --- a/msm/dp/dp_mst_drm.c +++ b/msm/dp/dp_mst_drm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ @@ -1204,8 +1204,8 @@ static int dp_mst_connector_atomic_check(struct drm_connector *connector, bridge->num_slots); } - /* do not attempt to release vcpi slots if crtc state is enable */ - if (drm_atomic_crtc_needs_modeset(crtc_state) && !crtc_state->enable) { + /*attempt to release vcpi slots on a modeset change for crtc state*/ + if (drm_atomic_crtc_needs_modeset(crtc_state)) { if (WARN_ON(!old_conn_state->best_encoder)) { rc = -EINVAL; goto end; From e6fa122c20d7f79adb1ddb4caf9aaf769d9e08b1 Mon Sep 17 00:00:00 2001 From: Lakshmi Narayana Kalavala Date: Thu, 23 Mar 2023 11:50:21 -0700 Subject: [PATCH 07/12] drm: msm: skip re-marking color processing features as dirty Current implementation we apply the color properties when atomic begin is called and mark features as dirty if crtc is not enabled. For some of the non double buffered features in video mode we will see a corruption. Change removes marking color properties as dirty based on crtc on/off. Change-Id: I4d93b14627d2bc06fcbca3ea9538a4baedb00e56 Signed-off-by: Lakshmi Narayana Kalavala --- msm/sde/sde_color_processing.c | 3 --- msm/sde/sde_crtc.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index e1fb7f5e..04ae2335 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -2243,9 +2243,6 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc) } _sde_cp_flush_properties(crtc); - if (!sde_crtc->enabled) - return; - mutex_lock(&sde_crtc->crtc_cp_lock); _sde_clear_ltm_merge_mode(sde_crtc); diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 56ae133b..42b93f97 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -4231,9 +4231,6 @@ static void _sde_crtc_atomic_begin(struct drm_crtc *crtc, if (sde_kms_is_cp_operation_allowed(sde_kms)) sde_cp_crtc_apply_properties(crtc); - if (!sde_crtc->enabled) - sde_cp_crtc_mark_features_dirty(crtc); - /* * PP_DONE irq is only used by command mode for now. * It is better to request pending before FLUSH and START trigger From 9ce2a6a09df3e1b2694c75c3adffc800067f6e5b Mon Sep 17 00:00:00 2001 From: Soutrik Mukhopadhyay Date: Tue, 14 Mar 2023 16:48:06 +0530 Subject: [PATCH 08/12] disp: msm: dp: check for atomic phase This change checks for the atomic state and ensures that allocation and deallocation of vcpi slots is prevented in the same phase. Change-Id: I05c87db43eca8ba749ed8a0907dcaf95945dd645 Signed-off-by: Soutrik Mukhopadhyay --- msm/dp/dp_mst_drm.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/msm/dp/dp_mst_drm.c b/msm/dp/dp_mst_drm.c index 155008db..bd2cb14d 100644 --- a/msm/dp/dp_mst_drm.c +++ b/msm/dp/dp_mst_drm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ @@ -1165,6 +1165,7 @@ static int dp_mst_connector_atomic_check(struct drm_connector *connector, void *display, struct drm_atomic_state *state) { int rc = 0, slots, i; + bool vcpi_released = false; struct drm_connector_state *old_conn_state; struct drm_connector_state *new_conn_state; struct drm_crtc *old_crtc; @@ -1239,6 +1240,7 @@ static int dp_mst_connector_atomic_check(struct drm_connector *connector, slots, rc); goto end; } + vcpi_released = true; } bridge_state->num_slots = 0; @@ -1284,6 +1286,15 @@ mode_set: goto end; } + /* + * check if vcpi slots are trying to get allocated in same phase + * as deallocation. If so, go to end to avoid allocation. + */ + if (vcpi_released) { + DP_WARN("skipping allocation since vcpi was released in the same state \n"); + goto end; + } + if (WARN_ON(bridge_state->num_slots)) { rc = -EINVAL; goto end; From ec4f833666c97c6d75e64fce8b0e4dd99f0e65b9 Mon Sep 17 00:00:00 2001 From: Mahadevan Date: Wed, 2 Nov 2022 12:45:54 +0530 Subject: [PATCH 09/12] disp: msm: sde: avoid white color solid fill staging on input fence timeout The issue is as follows: Commit N: 1. VIG sspp qseed block programmed through lutdma. LUTDMA packet with (ram offset, length_0) is queued to internal HW queue to enable scaler. 2. Input_fence timeout seen on VIG plane. 3. White color solid fill layer staged on VIG plane. 4. Disable VIG sspp qseed block through LUTDMA. LUTDMA packet is queued by overriding buffer with (ram offset, length_1) to internal HW queue to disable scaler. 5. Trigger_flush is picked by HW on vsync. Since 2 LUTDMA packets are queued on single vsync boundary pp_done timeout with lutdma HW hang is seen. The only way to fix this is to reset LUTDMA in step4 and then flush the Hardware. The current SW does not support this reset sequence, so the change avoids staging solid fill on input fence timeout. Change-Id: Ia243e42c863f56b11bee5aeed2dd434efcbd5d75 Signed-off-by: Mahadevan --- msm/sde/sde_plane.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/msm/sde/sde_plane.c b/msm/sde/sde_plane.c index d0365522..38a1d2ac 100644 --- a/msm/sde/sde_plane.c +++ b/msm/sde/sde_plane.c @@ -662,7 +662,6 @@ int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms) SDE_ERROR_PLANE(psde, "%ums timeout on %08X fd %lld\n", wait_ms, prefix, sde_plane_get_property(pstate, PLANE_PROP_INPUT_FENCE)); - psde->is_error = true; sde_kms_timeline_status(plane->dev); ret = -ETIMEDOUT; break; @@ -684,7 +683,6 @@ int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms) SDE_INFO("plane%d spec fd signaled on bind failure fd %lld\n", plane->base.id, sde_plane_get_property(pstate, PLANE_PROP_INPUT_FENCE)); - psde->is_error = true; ret = 0; break; default: From 5ce42a7435ff011f48530e0def9321442547e5c2 Mon Sep 17 00:00:00 2001 From: Yojana Juadi Date: Thu, 23 Feb 2023 12:19:43 +0530 Subject: [PATCH 10/12] disp: msm: sde: update idle_pc_duration based on frame rate This change updates the time required to enter idle_pc based on frame rate instead of default time. In the current issue, customer is facing janks where frame rate is 30fps and race happens between sde_encoder_off_work and drm_atomic_commit scheduled from userspace. It also sets max and min bound for optimized performance. Change-Id: I5e95e920a2f7b2142b5f63e8ce6b82cf1d482db1 Signed-off-by: Yojana Juadi --- msm/sde/sde_encoder.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 56033439..1107da4b 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -1986,8 +1986,10 @@ static void _sde_encoder_rc_restart_delayed(struct sde_encoder_virt *sde_enc, { struct drm_encoder *drm_enc = &sde_enc->base; struct msm_drm_private *priv; - unsigned int lp, idle_pc_duration; + unsigned int lp, idle_pc_duration, frame_time_ms, fps; struct msm_drm_thread *disp_thread; + unsigned int min_duration = IDLE_POWERCOLLAPSE_DURATION; + unsigned int max_duration = IDLE_POWERCOLLAPSE_IN_EARLY_WAKEUP; /* return early if called from esd thread */ if (sde_enc->delay_kickoff) @@ -2000,10 +2002,15 @@ static void _sde_encoder_rc_restart_delayed(struct sde_encoder_virt *sde_enc, else lp = SDE_MODE_DPMS_ON; + fps = sde_enc->mode_info.frame_rate; if ((lp == SDE_MODE_DPMS_LP1) || (lp == SDE_MODE_DPMS_LP2)) idle_pc_duration = IDLE_SHORT_TIMEOUT; - else - idle_pc_duration = IDLE_POWERCOLLAPSE_DURATION; + else { + frame_time_ms = 1000; + do_div(frame_time_ms, fps); + idle_pc_duration = max(4 * frame_time_ms, min_duration); + idle_pc_duration = min(idle_pc_duration, max_duration); + } priv = drm_enc->dev->dev_private; disp_thread = &priv->disp_thread[sde_enc->crtc->index]; From 0e2b3d56a29bd2fa358f01a68247344fc16278dc Mon Sep 17 00:00:00 2001 From: Mahadevan Date: Fri, 31 Mar 2023 01:40:49 +0530 Subject: [PATCH 11/12] disp: msm: sde: signal cwb retire fence on cwb overflow In the current SW, cwb overflow interrupt is not enabled for mid and low tier targets due to which CWB retire fence is not signaled, causing HWCBufferSyncHandler SyncWait timeouts on fence. This change enables the cwb overflow interrupt always to detect the overflow and signal the retire fence in such cases. Change-Id: I4841814d91bcd7b31f00554da6b2369078ce4693 Signed-off-by: Jayaprakash Madisetty Signed-off-by: Mahadevan --- msm/sde/sde_encoder_phys_wb.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/msm/sde/sde_encoder_phys_wb.c b/msm/sde/sde_encoder_phys_wb.c index d3897f52..d4fb117b 100644 --- a/msm/sde/sde_encoder_phys_wb.c +++ b/msm/sde/sde_encoder_phys_wb.c @@ -35,10 +35,6 @@ static const u32 cwb_irq_tbl[PINGPONG_MAX] = {SDE_NONE, INTR_IDX_PP1_OVFL, INTR_IDX_PP2_OVFL, INTR_IDX_PP3_OVFL, INTR_IDX_PP4_OVFL, INTR_IDX_PP5_OVFL, SDE_NONE, SDE_NONE}; -static const u32 dcwb_irq_tbl[PINGPONG_MAX] = {SDE_NONE, SDE_NONE, - SDE_NONE, SDE_NONE, SDE_NONE, SDE_NONE, - INTR_IDX_PP_CWB_OVFL, SDE_NONE}; - /** * sde_rgb2yuv_601l - rgb to yuv color space conversion matrix * @@ -1717,6 +1713,7 @@ static void sde_encoder_phys_wb_irq_ctrl(struct sde_encoder_phys *phys, bool ena int index = 0, pp = 0; u32 max_num_of_irqs = 0; const u32 *irq_table = NULL; + enum sde_intr_idx intr_idx; if (!wb_enc) return; @@ -1735,7 +1732,6 @@ static void sde_encoder_phys_wb_irq_ctrl(struct sde_encoder_phys *phys, bool ena wb_cfg = wb_enc->hw_wb->caps; if (wb_cfg->features & BIT(SDE_WB_HAS_DCWB)) { max_num_of_irqs = 1; - irq_table = dcwb_irq_tbl; } else { max_num_of_irqs = CRTC_DUAL_MIXERS_ONLY; irq_table = cwb_irq_tbl; @@ -1748,9 +1744,11 @@ static void sde_encoder_phys_wb_irq_ctrl(struct sde_encoder_phys *phys, bool ena if (test_bit(SDE_WB_PROG_LINE, &wb_cfg->features)) sde_encoder_helper_register_irq(phys, INTR_IDX_WB_LINEPTR); - for (index = 0; index < max_num_of_irqs; index++) - if (irq_table[index + pp] != SDE_NONE) - sde_encoder_helper_register_irq(phys, irq_table[index + pp]); + for (index = 0; index < max_num_of_irqs; index++) { + intr_idx = irq_table ? irq_table[index + pp] : INTR_IDX_PP_CWB_OVFL; + if (intr_idx != SDE_NONE) + sde_encoder_helper_register_irq(phys, intr_idx); + } } else if (!enable && atomic_dec_return(&phys->wbirq_refcount) == 0) { sde_encoder_helper_unregister_irq(phys, INTR_IDX_WB_DONE); sde_encoder_helper_unregister_irq(phys, INTR_IDX_CTL_START); @@ -1758,9 +1756,11 @@ static void sde_encoder_phys_wb_irq_ctrl(struct sde_encoder_phys *phys, bool ena if (test_bit(SDE_WB_PROG_LINE, &wb_cfg->features)) sde_encoder_helper_unregister_irq(phys, INTR_IDX_WB_LINEPTR); - for (index = 0; index < max_num_of_irqs; index++) - if (irq_table[index + pp] != SDE_NONE) - sde_encoder_helper_unregister_irq(phys, irq_table[index + pp]); + for (index = 0; index < max_num_of_irqs; index++) { + intr_idx = irq_table ? irq_table[index + pp] : INTR_IDX_PP_CWB_OVFL; + if (intr_idx != SDE_NONE) + sde_encoder_helper_unregister_irq(phys, intr_idx); + } } } From e4a6f53bff3f1c5bd5bba0ef1e2a5bfe03656caa Mon Sep 17 00:00:00 2001 From: Anand Tarakh Date: Thu, 23 Feb 2023 15:33:21 +0530 Subject: [PATCH 12/12] disp: msm: dsi: add mutex lock before link clock frequency update Acquire mngr clk_mutex before updating link clock frequencies. Failing this may lead to race around condition while setting the link clock frequency rates. Make sure byteclk and pclk rates of PLL are configured according to clock manager and not the controller. Change-Id: I2cd26e659ce166d5bc55eb6c060672eeee192bea Signed-off-by: Anand Tarakh --- msm/dsi/dsi_clk.h | 23 ++++++++++++++- msm/dsi/dsi_clk_manager.c | 50 +++++++++++++++++++++++++++++++ msm/dsi/dsi_ctrl.c | 7 +---- msm/dsi/dsi_display.c | 62 ++++++++++++++++++++++++++++++++------- 4 files changed, 125 insertions(+), 17 deletions(-) diff --git a/msm/dsi/dsi_clk.h b/msm/dsi/dsi_clk.h index 8a45460f..b9d71980 100644 --- a/msm/dsi/dsi_clk.h +++ b/msm/dsi/dsi_clk.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -301,6 +302,15 @@ int dsi_display_clk_ctrl(void *handle, u32 clk_type, u32 clk_state); int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, u32 index); +/** + * dsi_clk_get_link_frequencies() - get link clk frequencies + * @link_freq: Structure to get link clock frequencies + * @client: DSI clock client pointer. + * @index: Index of the DSI controller. + * + * return: error code in case of failure or 0 for success. + */ +int dsi_clk_get_link_frequencies(struct link_clk_freq *link_freq, void *client, u32 index); /** * dsi_clk_set_pixel_clk_rate() - set frequency for pixel_clk @@ -311,7 +321,6 @@ int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, */ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index); - /** * dsi_clk_set_byte_clk_rate() - set frequency for byte clock * @client: DSI clock client pointer. @@ -351,4 +360,16 @@ void dsi_clk_disable_unprepare(struct dsi_clk_link_set *clk); */ int dsi_display_dump_clk_handle_state(void *client); +/** + * dsi_clk_acquire_mngr_lock() - acquire clk manager mutex lock + * @client: DSI clock client pointer. + */ +void dsi_clk_acquire_mngr_lock(void *client); + +/** + * dsi_clk_release_mngr_lock() - release clk manager mutex lock + * @client: DSI clock client pointer. + */ +void dsi_clk_release_mngr_lock(void *client); + #endif /* _DSI_CLK_H_ */ diff --git a/msm/dsi/dsi_clk_manager.c b/msm/dsi/dsi_clk_manager.c index e52465ff..18661b72 100644 --- a/msm/dsi/dsi_clk_manager.c +++ b/msm/dsi/dsi_clk_manager.c @@ -105,6 +105,30 @@ int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, return rc; } +/** + * dsi_clk_get_link_frequencies() - get link clk frequencies + * @link_freq: Structure to get link clock frequencies + * @client: DSI clock client pointer. + * @index: Index of the DSI controller. + * + * return: error code in case of failure or 0 for success. + */ +int dsi_clk_get_link_frequencies(struct link_clk_freq *link_freq, void *client, u32 index) +{ + struct dsi_clk_client_info *c = client; + struct dsi_clk_mngr *mngr; + + if (!client || !link_freq) { + DSI_ERR("invalid params\n"); + return -EINVAL; + } + + mngr = c->mngr; + memcpy(link_freq, &mngr->link_clks[index].freq, sizeof(struct link_clk_freq)); + + return 0; +} + /** * dsi_clk_set_pixel_clk_rate() - set frequency for pixel clock * @clks: DSI link clock information. @@ -1493,3 +1517,29 @@ int dsi_display_clk_mngr_deregister(void *clk_mngr) kfree(mngr); return rc; } + +/** + * dsi_clk_acquire_mngr_lock() - acquire clk manager mutex lock + * @client: DSI clock client pointer. + */ +void dsi_clk_acquire_mngr_lock(void *client) +{ + struct dsi_clk_mngr *mngr; + struct dsi_clk_client_info *c = client; + + mngr = c->mngr; + mutex_lock(&mngr->clk_mutex); +} + +/** + * dsi_clk_release_mngr_lock() - release clk manager mutex lock + * @client: DSI clock client pointer. + */ +void dsi_clk_release_mngr_lock(void *client) +{ + struct dsi_clk_mngr *mngr; + struct dsi_clk_client_info *c = client; + + mngr = c->mngr; + mutex_unlock(&mngr->clk_mutex); +} diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index 3393de05..53587ff9 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -1104,11 +1104,6 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl, dsi_ctrl->clk_freq.pix_clk_rate = pclk_rate; dsi_ctrl->clk_freq.esc_clk_rate = config->esc_clk_rate_hz; - rc = dsi_clk_set_link_frequencies(clk_handle, dsi_ctrl->clk_freq, - dsi_ctrl->cell_index); - if (rc) - DSI_CTRL_ERR(dsi_ctrl, "Failed to update link frequencies\n"); - return rc; } diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 16a27aaa..e03eb343 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -2826,7 +2826,7 @@ int dsi_display_phy_configure(void *priv, bool commit) struct dsi_display *display = priv; struct dsi_display_ctrl *m_ctrl; struct dsi_pll_resource *pll_res; - struct dsi_ctrl *ctrl; + struct link_clk_freq link_freq; if (!display) { DSI_ERR("invalid arguments\n"); @@ -2848,9 +2848,15 @@ int dsi_display_phy_configure(void *priv, bool commit) return -EINVAL; } - ctrl = m_ctrl->ctrl; - pll_res->byteclk_rate = ctrl->clk_freq.byte_clk_rate; - pll_res->pclk_rate = ctrl->clk_freq.pix_clk_rate; + rc = dsi_clk_get_link_frequencies(&link_freq, display->dsi_clk_handle, + display->clk_master_idx); + if (rc) { + DSI_ERR("Failed to get link frequencies\n"); + return rc; + } + + pll_res->byteclk_rate = link_freq.byte_clk_rate; + pll_res->pclk_rate = link_freq.pix_clk_rate; rc = dsi_phy_configure(m_ctrl->phy, commit); @@ -4458,6 +4464,26 @@ void dsi_display_update_byte_intf_div(struct dsi_display *display) config->byte_intf_clk_div = 2; } +static int dsi_display_set_link_frequencies(struct dsi_display *display) +{ + int rc = 0, i = 0; + + dsi_clk_acquire_mngr_lock(display->dsi_clk_handle); + display_for_each_ctrl(i, display) { + struct dsi_display_ctrl *ctrl = &display->ctrl[i]; + + rc = dsi_clk_set_link_frequencies(display->dsi_clk_handle, ctrl->ctrl->clk_freq, i); + if (rc) { + DSI_ERR("Failed to update link frequencies of ctrl_%d, rc=%d\n", i, rc); + dsi_clk_release_mngr_lock(display->dsi_clk_handle); + return rc; + } + } + dsi_clk_release_mngr_lock(display->dsi_clk_handle); + + return rc; +} + static int dsi_display_update_dsi_bitrate(struct dsi_display *display, u32 bit_clk_rate) { @@ -4540,12 +4566,6 @@ static int dsi_display_update_dsi_bitrate(struct dsi_display *display, ctrl->clk_freq.byte_clk_rate = byte_clk_rate; ctrl->clk_freq.byte_intf_clk_rate = byte_intf_clk_rate; ctrl->clk_freq.pix_clk_rate = pclk_rate; - rc = dsi_clk_set_link_frequencies(display->dsi_clk_handle, - ctrl->clk_freq, ctrl->cell_index); - if (rc) { - DSI_ERR("Failed to update link frequencies\n"); - goto error; - } ctrl->host_config.bit_clk_rate_hz = bit_clk_rate; error: @@ -4556,6 +4576,12 @@ error: return rc; } + rc = dsi_display_set_link_frequencies(display); + if (rc) { + DSI_ERR("Failed to set display link frequencies\n"); + return rc; + } + return 0; } @@ -5210,6 +5236,15 @@ static int dsi_display_set_mode_sub(struct dsi_display *display, } } + if (!(mode->dsi_mode_flags & (DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR | + DSI_MODE_FLAG_DYN_CLK))) { + rc = dsi_display_set_link_frequencies(display); + if (rc) { + DSI_ERR("Failed to set display link frequencies\n"); + goto error; + } + } + if ((mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) && (display->panel->panel_mode == DSI_OP_CMD_MODE)) { u64 cur_bitclk = display->panel->cur_mode->timing.clk_rate_hz; @@ -7408,6 +7443,13 @@ int dsi_display_update_transfer_time(void *display, u32 transfer_time) return rc; } } + + rc = dsi_display_set_link_frequencies(disp); + if (rc) { + DSI_ERR("Failed to set display link frequencies\n"); + return rc; + } + atomic_set(&disp->clkrate_change_pending, 1); return 0;