From b45b583f53472a40d53908921bb2e0c03d4547aa Mon Sep 17 00:00:00 2001 From: Jayaprakash Madisetty Date: Thu, 26 Aug 2021 17:10:18 +0530 Subject: [PATCH 1/5] disp: msm: sde: use fixed prefill lines in rscc static wakeup calculation In dual display during bootup, panel prefill lines may be used in configuring rscc static wakeup due to ongoing autorefresh in secondary display. Due to this, there can be a case when transfer time for the commit is greater than the static wakeup calculated when panel has large prefill lines(vbp + vpw + vfp) causing janks on primary when secondary display enters idle and primary display is running. Add changes to use default_prefill_lines for configuring static wakeup during bootup when rsc is in clk state. For vid state only, panel prefill lines will be taken into account for rsc static wakeup calculation. Change-Id: I3c0ceec984b24b81e3e4d0341f25cdd28f178925 Signed-off-by: Jayaprakash Madisetty --- msm/sde_rsc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msm/sde_rsc.c b/msm/sde_rsc.c index e06b5f7fe937..75dcb932a77d 100644 --- a/msm/sde_rsc.c +++ b/msm/sde_rsc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[sde_rsc:%s:%d]: " fmt, __func__, __LINE__ @@ -310,7 +310,7 @@ static u32 sde_rsc_timer_calculate(struct sde_rsc_priv *rsc, default_prefill_lines = (rsc->cmd_config.fps * DEFAULT_PANEL_MIN_V_PREFILL) / DEFAULT_PANEL_FPS; - if ((state == SDE_RSC_CMD_STATE) || !rsc->cmd_config.prefill_lines) + if ((state != SDE_RSC_VID_STATE) || !rsc->cmd_config.prefill_lines) rsc->cmd_config.prefill_lines = default_prefill_lines; pr_debug("frame fps:%d jitter_numer:%d jitter_denom:%d vtotal:%d prefill lines:%d\n", From a83f22243d7a4ca57b531ab1a7ded5707138ce0c Mon Sep 17 00:00:00 2001 From: Ping Li Date: Wed, 7 Apr 2021 15:18:42 -0700 Subject: [PATCH 2/5] msm: sde: disp: Set merge_mode after vlut and hist enable To ensure that set merge_mode after vlut and hist enable, move merge_mode enable from ltm_init to ltm_vlut. Redefine the OP_MASK of LTM_INIT_ENABLE and LTM_VLUT_ENABLE, in order to write the merge_mode bits correctly. Change-Id: I5258e7f545e265b114098e46d31986274127e962 Signed-off-by: Ping Li Signed-off-by: Yuchao Ma --- msm/sde/sde_color_processing.c | 5 ++++- msm/sde/sde_hw_reg_dma_v1_color_proc.c | 27 +++++++++++++------------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index 28e23b304693..db9367a2db6b 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -1993,6 +1993,7 @@ static void _sde_clear_ltm_merge_mode(struct sde_crtc *sde_crtc) } sde_crtc->ltm_merge_clear_pending = false; + SDE_EVT32(DRMID(&sde_crtc->base), num_mixers, sde_crtc->ltm_merge_clear_pending); spin_unlock_irqrestore(&sde_crtc->ltm_lock, irq_flags); } @@ -2346,6 +2347,7 @@ void sde_cp_crtc_destroy_properties(struct drm_crtc *crtc) sde_crtc->ltm_buffer_cnt = 0; sde_crtc->ltm_hist_en = false; sde_crtc->ltm_merge_clear_pending = false; + SDE_EVT32(DRMID(crtc), sde_crtc->ltm_merge_clear_pending); sde_crtc->hist_irq_idx = -1; mutex_destroy(&sde_crtc->crtc_cp_lock); @@ -2391,7 +2393,6 @@ void sde_cp_crtc_suspend(struct drm_crtc *crtc) spin_lock_irqsave(&sde_crtc->ltm_lock, irq_flags); sde_crtc->ltm_hist_en = false; - sde_crtc->ltm_merge_clear_pending = false; spin_unlock_irqrestore(&sde_crtc->ltm_lock, irq_flags); if (ad_suspend) @@ -3833,6 +3834,7 @@ static void _sde_cp_crtc_disable_ltm_hist(struct sde_crtc *sde_crtc, spin_lock_irqsave(&sde_crtc->ltm_lock, irq_flags); sde_crtc->ltm_hist_en = false; sde_crtc->ltm_merge_clear_pending = true; + SDE_EVT32(DRMID(&sde_crtc->base), sde_crtc->ltm_merge_clear_pending); INIT_LIST_HEAD(&sde_crtc->ltm_buf_free); INIT_LIST_HEAD(&sde_crtc->ltm_buf_busy); for (i = 0; i < sde_crtc->ltm_buffer_cnt; i++) @@ -3905,6 +3907,7 @@ static void sde_cp_ltm_hist_interrupt_cb(void *arg, int irq_idx) 0); } sde_crtc->ltm_merge_clear_pending = true; + SDE_EVT32(DRMID(&sde_crtc->base), sde_crtc->ltm_merge_clear_pending); spin_unlock_irqrestore(&sde_crtc->ltm_lock, irq_flags); DRM_DEBUG_DRIVER("LTM histogram is disabled\n"); return; diff --git a/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/msm/sde/sde_hw_reg_dma_v1_color_proc.c index 7295d8d52870..42d2a885ab5e 100644 --- a/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -29,19 +29,19 @@ #define PA_LUTV_DSPP_CTRL_OFF 0x4c #define PA_LUTV_DSPP_SWAP_OFF 0x18 /** - * the diff between LTM_INIT_ENABLE/DISABLE masks are portrait_en and - * merge_mode bits. When disabling INIT property, we don't want to reset those - * bits since they are needed for both LTM histogram and VLUT. + * the diff between LTM_INIT_ENABLE/DISABLE masks is portrait_en bits. + * When disabling INIT property, we don't want to reset those bits since + * they are needed for both LTM histogram and VLUT. */ -#define REG_DMA_LTM_INIT_ENABLE_OP_MASK 0xFFFC8CAB +#define REG_DMA_LTM_INIT_ENABLE_OP_MASK 0xFFFF8CAB #define REG_DMA_LTM_INIT_DISABLE_OP_MASK 0xFFFF8CAF #define REG_DMA_LTM_ROI_OP_MASK 0xFEFFFFFF /** - * the diff between LTM_VLUT_ENABLE/DISABLE masks are dither strength and - * unsharp_gain bits. When disabling VLUT property, we want to reset these - * bits since those are only valid if VLUT is enabled. + * the diff between LTM_VLUT_ENABLE/DISABLE masks are merge_mode, dither + * strength and unsharp_gain bits. When disabling VLUT property, we want + * to reset these bits since those are only valid if VLUT is enabled. */ -#define REG_DMA_LTM_VLUT_ENABLE_OP_MASK 0xFEFFFFAD +#define REG_DMA_LTM_VLUT_ENABLE_OP_MASK 0xFEFCFFAD #define REG_DMA_LTM_VLUT_DISABLE_OP_MASK 0xFEFF8CAD #define REG_DMA_LTM_UPDATE_REQ_MASK 0xFFFFFFFE @@ -3518,11 +3518,6 @@ void reg_dmav1_setup_ltm_initv1(struct sde_hw_dspp *ctx, void *cfg) else opmode &= ~BIT(2); - if (phase.merge_en) - opmode |= BIT(16); - else - opmode &= ~(BIT(16) | BIT(17)); - phase_data[0] = phase.init_v; phase_data[1] = phase.inc_h; phase_data[2] = phase.inc_v; @@ -3815,6 +3810,7 @@ void reg_dmav1_setup_ltm_vlutv1(struct sde_hw_dspp *ctx, void *cfg) struct sde_hw_cp_cfg *hw_cfg = cfg; struct sde_reg_dma_kickoff_cfg kick_off; struct sde_hw_reg_dma_ops *dma_ops; + struct sde_ltm_phase_info phase; enum sde_ltm dspp_idx[LTM_MAX] = {0}; enum sde_ltm idx = 0; u32 offset, crs = 0, index = 0, len = 0, blk = 0, opmode = 0; @@ -3885,6 +3881,7 @@ void reg_dmav1_setup_ltm_vlutv1(struct sde_hw_dspp *ctx, void *cfg) return; } + sde_ltm_get_phase_info(hw_cfg, &phase); for (i = 0; i < num_mixers; i++) { /* broadcast feature is not supported with REG_SINGLE_MODIFY */ /* reset decode select to unicast */ @@ -3915,6 +3912,10 @@ void reg_dmav1_setup_ltm_vlutv1(struct sde_hw_dspp *ctx, void *cfg) opmode |= BIT(6); if (ltm_vlut_ops_mask[dspp_idx[i]] & ltm_roi) opmode |= BIT(24); + if (phase.merge_en) + opmode |= BIT(16); + else + opmode &= ~(BIT(16) | BIT(17)); ltm_vlut_ops_mask[dspp_idx[i]] |= ltm_vlut; REG_DMA_SETUP_OPS(dma_write_cfg, 0x4, &opmode, sizeof(u32), From 1e1c1a4a1ccbf701ca71ee0be86a0c9be89154ee Mon Sep 17 00:00:00 2001 From: Anjaneya Prasad Musunuri Date: Wed, 1 Sep 2021 12:04:04 +0530 Subject: [PATCH 3/5] disp: msm: sde: clear partial update mask during last close Clear partial update mask during last close to avoid rounded corner to be programmed without valid mask during shell stop/start operations. Change-Id: I378adc62b5bc5913abfc32fa3528c8e28ea273d4 Signed-off-by: Anjaneya Prasad Musunuri --- msm/sde/sde_color_processing.c | 1 + 1 file changed, 1 insertion(+) diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index 28e23b304693..7ea8b4e466a2 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -2424,6 +2424,7 @@ void sde_cp_crtc_clear(struct drm_crtc *crtc) list_del_init(&sde_crtc->dirty_list); list_del_init(&sde_crtc->ad_active); list_del_init(&sde_crtc->ad_dirty); + sde_crtc->cp_pu_feature_mask = 0; mutex_unlock(&sde_crtc->crtc_cp_lock); spin_lock_irqsave(&sde_crtc->spin_lock, flags); From f6d96209a5510d52caaf380ae3938697cbd9330b Mon Sep 17 00:00:00 2001 From: Srihitha Tangudu Date: Wed, 8 Sep 2021 15:21:00 +0530 Subject: [PATCH 4/5] disp: msm: dsi: Fix deadlock issue in debugfs_esd_trigger_check function In debugfs_esd_trigger_check, display mutex is not unlocked in error scenario which may lead to deadlock. This change adds fix to handle this. Change-Id: I44d78959630a49bd1e9dcf871cfc108ac43232db Signed-off-by: Srihitha Tangudu --- msm/dsi/dsi_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 9cf97c164e70..361bb5528bae 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -1562,7 +1562,7 @@ static ssize_t debugfs_esd_trigger_check(struct file *file, display->trusted_vm_env); if (rc) { DSI_ERR("Failed to trigger ESD attack\n"); - goto error; + goto unlock; } } From ad3b81ed30d3578ca9f69028fdbbc6b60541666a Mon Sep 17 00:00:00 2001 From: Lei Chen Date: Thu, 9 Sep 2021 14:18:15 +0800 Subject: [PATCH 5/5] disp: msm: qpic: fix kw issues in QPIC display driver This change is updated to address use after free and null checks in QPIC display driver. Change-Id: I97f1d941de69aad3d49cbf0c9782022b8f7db840 Signed-off-by: Lei Chen --- tinydrm/qpic_display.c | 18 +++++++++++++----- tinydrm/qpic_display.h | 2 +- tinydrm/qpic_panel_ili9341.c | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/tinydrm/qpic_display.c b/tinydrm/qpic_display.c index d000751bdd76..d32241db2b2c 100644 --- a/tinydrm/qpic_display.c +++ b/tinydrm/qpic_display.c @@ -918,14 +918,22 @@ static const struct drm_mode_config_funcs qpic_mode_config_funcs = { static void qpic_display_fb_mark_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) { u32 size; - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); - struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; + struct drm_gem_cma_object *cma_obj = NULL; + struct dma_buf_attachment *import_attach = NULL; struct qpic_display_data *qpic_display = fb->dev->dev_private; if (!qpic_display->is_qpic_on || !qpic_display->is_panel_on) { pr_info("%s: qpic or panel is not enabled\n", __func__); return; } + + cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + if (!cma_obj) { + pr_err("failed to get gem obj\n"); + return; + } + import_attach = cma_obj->base.import_attach; + /* currently QPIC display SW can't support partial updates */ rect->x1 = 0; rect->x2 = fb->width; @@ -1194,7 +1202,7 @@ int qpic_display_get_resource(struct qpic_display_data *qpic_display) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qpic_base"); if (!res) { pr_err("unable to get QPIC reg base address\n"); - rc = -ENOMEM; + return -ENOMEM; } qpic_display->qpic_reg_size = resource_size(res); @@ -1202,7 +1210,7 @@ int qpic_display_get_resource(struct qpic_display_data *qpic_display) qpic_display->qpic_reg_size); if (unlikely(!qpic_display->qpic_base)) { pr_err("unable to map MDSS QPIC base\n"); - rc = -ENOMEM; + return -ENOMEM; } qpic_display->qpic_phys = res->start; pr_info("MDSS QPIC HW Base phy_Address=0x%x virt=0x%x\n", @@ -1212,7 +1220,7 @@ int qpic_display_get_resource(struct qpic_display_data *qpic_display) res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { pr_err("unable to get QPIC irq\n"); - rc = -ENODEV; + return -ENODEV; } qpic_display->qpic_clk = devm_clk_get(&pdev->dev, "core_clk"); diff --git a/tinydrm/qpic_display.h b/tinydrm/qpic_display.h index 7e5af6e3a885..a91a99ba77b1 100644 --- a/tinydrm/qpic_display.h +++ b/tinydrm/qpic_display.h @@ -132,6 +132,6 @@ struct qpic_display_data { }; -int get_ili_qvga_panel_config(struct qpic_display_data *qpic_display); +void get_ili_qvga_panel_config(struct qpic_display_data *qpic_display); #endif diff --git a/tinydrm/qpic_panel_ili9341.c b/tinydrm/qpic_panel_ili9341.c index 757dfd2a7371..db47abbf8172 100644 --- a/tinydrm/qpic_panel_ili9341.c +++ b/tinydrm/qpic_panel_ili9341.c @@ -76,7 +76,7 @@ static struct qpic_panel_config ili_qvga_panel = { .bpp = 16, }; -int get_ili_qvga_panel_config(struct qpic_display_data *qpic_display) +void get_ili_qvga_panel_config(struct qpic_display_data *qpic_display) { qpic_display->panel_config = &ili_qvga_panel; qpic_display->panel_on = ili9341_on;