From 5333f0ecf73800c0b503c0c257e0be39fcf316b1 Mon Sep 17 00:00:00 2001 From: Changcheng Deng Date: Tue, 21 Dec 2021 14:42:34 +0000 Subject: [PATCH 01/70] drm/msm: replace DEFINE_SIMPLE_ATTRIBUTE with DEFINE_DEBUGFS_ATTRIBUTE Fix the following coccicheck warning: ./drivers/gpu/drm/msm/msm_debugfs.c: 132: 0-23: WARNING: shrink_fops should be defined with DEFINE_DEBUGFS_ATTRIBUTE Use DEFINE_DEBUGFS_ATTRIBUTE rather than DEFINE_SIMPLE_ATTRIBUTE for debugfs files. Reported-by: Zeal Robot Signed-off-by: Changcheng Deng Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20211221144234.480618-1-deng.changcheng@zte.com.cn Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/msm_debugfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c index 0804c31e89629..ea2a20699cb40 100644 --- a/drivers/gpu/drm/msm/msm_debugfs.c +++ b/drivers/gpu/drm/msm/msm_debugfs.c @@ -201,9 +201,9 @@ shrink_set(void *data, u64 val) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(shrink_fops, - shrink_get, shrink_set, - "0x%08llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(shrink_fops, + shrink_get, shrink_set, + "0x%08llx\n"); static int msm_gem_show(struct seq_file *m, void *arg) From 897f55049fe085e26fac82eed0ae0de8e47a4808 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 6 Jan 2022 02:26:58 +0300 Subject: [PATCH 02/70] drm/msm: drop register logging support Register logging was used during early stages of msm driver development to compare upstream and downstream register traces. However the tool was never updated to work with mdp5 hardware. Later it was dropped completely when Rob imported freedreno tools into mesa. All this makes DRM_MSM_REGISTER_LOGGING irrelevant now, so it can be dropped. Signed-off-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20220105232700.444170-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/Kconfig | 9 --------- drivers/gpu/drm/msm/msm_drv.c | 16 +--------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 1eae5a9645f41..9b019598e042e 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -33,15 +33,6 @@ config DRM_MSM_GPU_STATE depends on DRM_MSM && (DEBUG_FS || DEV_COREDUMP) default y -config DRM_MSM_REGISTER_LOGGING - bool "MSM DRM register logging" - depends on DRM_MSM - default n - help - Compile in support for logging register reads/writes in a format - that can be parsed by envytools demsm tool. If enabled, register - logging can be switched on via msm.reglog=y module param. - config DRM_MSM_GPU_SUDO bool "Enable SUDO flag on submits" depends on DRM_MSM && EXPERT diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 555666e3f9603..1145e06513df5 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -57,14 +57,6 @@ static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = { .atomic_commit_tail = msm_atomic_commit_tail, }; -#ifdef CONFIG_DRM_MSM_REGISTER_LOGGING -static bool reglog; -MODULE_PARM_DESC(reglog, "Enable register read/write logging"); -module_param(reglog, bool, 0600); -#else -#define reglog 0 -#endif - #ifdef CONFIG_DRM_FBDEV_EMULATION static bool fbdev = true; MODULE_PARM_DESC(fbdev, "Enable fbdev compat layer"); @@ -150,9 +142,6 @@ static void __iomem *_msm_ioremap(struct platform_device *pdev, const char *name return ERR_PTR(-ENOMEM); } - if (reglog) - printk(KERN_DEBUG "IO:region %s %p %08lx\n", dbgname, ptr, size); - if (psize) *psize = size; @@ -179,16 +168,13 @@ void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name, void msm_writel(u32 data, void __iomem *addr) { - if (reglog) - printk(KERN_DEBUG "IO:W %p %08x\n", addr, data); writel(data, addr); } u32 msm_readl(const void __iomem *addr) { u32 val = readl(addr); - if (reglog) - pr_err("IO:R %p %08x\n", addr, val); + return val; } From c0e745d73a51c65092fd21fd3022153e9e611ff0 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 6 Jan 2022 02:26:59 +0300 Subject: [PATCH 03/70] drm/msm: drop dbgname argument from msm_ioremap*() msm_ioremap() functions take additional argument dbgname which is now unused. Signed-off-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20220105232700.444170-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 8 ++++---- drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 2 +- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 2 +- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 2 +- drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c | 4 ++-- drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 8 ++++---- drivers/gpu/drm/msm/hdmi/hdmi.c | 5 ++--- drivers/gpu/drm/msm/hdmi/hdmi_phy.c | 2 +- drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c | 7 +++---- drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c | 2 +- drivers/gpu/drm/msm/msm_drv.c | 16 +++++++--------- drivers/gpu/drm/msm/msm_drv.h | 8 +++----- drivers/gpu/drm/msm/msm_gpu.c | 2 +- 15 files changed, 33 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 17cfad6424db6..83e5c09c7d4b1 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1506,7 +1506,7 @@ static void a6xx_llc_slices_init(struct platform_device *pdev, if (a6xx_gpu->have_mmu500) a6xx_gpu->llc_mmio = NULL; else - a6xx_gpu->llc_mmio = msm_ioremap(pdev, "cx_mem", "gpu_cx"); + a6xx_gpu->llc_mmio = msm_ioremap(pdev, "cx_mem"); a6xx_gpu->llc_slice = llcc_slice_getd(LLCC_GPU); a6xx_gpu->htw_llc_slice = llcc_slice_getd(LLCC_GPUHTW); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 47fe11a84a77c..201c0e3082ddb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1043,7 +1043,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) atomic_set(&dpu_kms->bandwidth_ref, 0); - dpu_kms->mmio = msm_ioremap(dpu_kms->pdev, "mdp", "mdp"); + dpu_kms->mmio = msm_ioremap(dpu_kms->pdev, "mdp"); if (IS_ERR(dpu_kms->mmio)) { rc = PTR_ERR(dpu_kms->mmio); DPU_ERROR("mdp register memory map failed: %d\n", rc); @@ -1052,20 +1052,20 @@ static int dpu_kms_hw_init(struct msm_kms *kms) } DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio); - dpu_kms->vbif[VBIF_RT] = msm_ioremap(dpu_kms->pdev, "vbif", "vbif"); + dpu_kms->vbif[VBIF_RT] = msm_ioremap(dpu_kms->pdev, "vbif"); if (IS_ERR(dpu_kms->vbif[VBIF_RT])) { rc = PTR_ERR(dpu_kms->vbif[VBIF_RT]); DPU_ERROR("vbif register memory map failed: %d\n", rc); dpu_kms->vbif[VBIF_RT] = NULL; goto error; } - dpu_kms->vbif[VBIF_NRT] = msm_ioremap_quiet(dpu_kms->pdev, "vbif_nrt", "vbif_nrt"); + dpu_kms->vbif[VBIF_NRT] = msm_ioremap_quiet(dpu_kms->pdev, "vbif_nrt"); if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) { dpu_kms->vbif[VBIF_NRT] = NULL; DPU_DEBUG("VBIF NRT is not defined"); } - dpu_kms->reg_dma = msm_ioremap_quiet(dpu_kms->pdev, "regdma", "regdma"); + dpu_kms->reg_dma = msm_ioremap_quiet(dpu_kms->pdev, "regdma"); if (IS_ERR(dpu_kms->reg_dma)) { dpu_kms->reg_dma = NULL; DPU_DEBUG("REG_DMA is not defined"); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c index 131c1f1a869c1..5bdb1504035ce 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -222,7 +222,7 @@ int dpu_mdss_init(struct platform_device *pdev) if (!dpu_mdss) return -ENOMEM; - dpu_mdss->mmio = msm_ioremap(pdev, "mdss", "mdss"); + dpu_mdss->mmio = msm_ioremap(pdev, "mdss"); if (IS_ERR(dpu_mdss->mmio)) return PTR_ERR(dpu_mdss->mmio); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index 5a33bb148e9ef..3cf476c551584 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -418,7 +418,7 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev) mdp4_kms->dev = dev; - mdp4_kms->mmio = msm_ioremap(pdev, NULL, "MDP4"); + mdp4_kms->mmio = msm_ioremap(pdev, NULL); if (IS_ERR(mdp4_kms->mmio)) { ret = PTR_ERR(mdp4_kms->mmio); goto fail; diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 12a5f81e402bd..81bd434980cfe 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -827,7 +827,7 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) if (ret) goto fail; - mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5"); + mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys"); if (IS_ERR(mdp5_kms->mmio)) { ret = PTR_ERR(mdp5_kms->mmio); goto fail; diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c index b3f79c2277e9d..049c6784a531b 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c @@ -210,13 +210,13 @@ int mdp5_mdss_init(struct platform_device *pdev) mdp5_mdss->base.dev = &pdev->dev; - mdp5_mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS"); + mdp5_mdss->mmio = msm_ioremap(pdev, "mdss_phys"); if (IS_ERR(mdp5_mdss->mmio)) { ret = PTR_ERR(mdp5_mdss->mmio); goto fail; } - mdp5_mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); + mdp5_mdss->vbif = msm_ioremap(pdev, "vbif_phys"); if (IS_ERR(mdp5_mdss->vbif)) { ret = PTR_ERR(mdp5_mdss->vbif); goto fail; diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 6b3ced4aaaf5d..8b15280261b8a 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1813,7 +1813,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) goto fail; } - msm_host->ctrl_base = msm_ioremap_size(pdev, "dsi_ctrl", "DSI CTRL", &msm_host->ctrl_size); + msm_host->ctrl_base = msm_ioremap_size(pdev, "dsi_ctrl", &msm_host->ctrl_size); if (IS_ERR(msm_host->ctrl_base)) { pr_err("%s: unable to map Dsi ctrl base\n", __func__); ret = PTR_ERR(msm_host->ctrl_base); diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 2027b38617ab2..745ee68565c9a 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -709,14 +709,14 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) if (!of_property_read_u32(dev->of_node, "phy-type", &phy_type)) phy->cphy_mode = (phy_type == PHY_TYPE_CPHY); - phy->base = msm_ioremap_size(pdev, "dsi_phy", "DSI_PHY", &phy->base_size); + phy->base = msm_ioremap_size(pdev, "dsi_phy", &phy->base_size); if (IS_ERR(phy->base)) { DRM_DEV_ERROR(dev, "%s: failed to map phy base\n", __func__); ret = -ENOMEM; goto fail; } - phy->pll_base = msm_ioremap_size(pdev, "dsi_pll", "DSI_PLL", &phy->pll_size); + phy->pll_base = msm_ioremap_size(pdev, "dsi_pll", &phy->pll_size); if (IS_ERR(phy->pll_base)) { DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__); ret = -ENOMEM; @@ -724,7 +724,7 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) } if (phy->cfg->has_phy_lane) { - phy->lane_base = msm_ioremap_size(pdev, "dsi_phy_lane", "DSI_PHY_LANE", &phy->lane_size); + phy->lane_base = msm_ioremap_size(pdev, "dsi_phy_lane", &phy->lane_size); if (IS_ERR(phy->lane_base)) { DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy lane base\n", __func__); ret = -ENOMEM; @@ -733,7 +733,7 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) } if (phy->cfg->has_phy_regulator) { - phy->reg_base = msm_ioremap_size(pdev, "dsi_phy_regulator", "DSI_PHY_REG", &phy->reg_size); + phy->reg_base = msm_ioremap_size(pdev, "dsi_phy_regulator", &phy->reg_size); if (IS_ERR(phy->reg_base)) { DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy regulator base\n", __func__); ret = -ENOMEM; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 719720709e9e7..1d56529168a9c 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -133,7 +133,7 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) hdmi->config = config; spin_lock_init(&hdmi->reg_lock); - hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI"); + hdmi->mmio = msm_ioremap(pdev, config->mmio_name); if (IS_ERR(hdmi->mmio)) { ret = PTR_ERR(hdmi->mmio); goto fail; @@ -144,8 +144,7 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) config->mmio_name); hdmi->mmio_phy_addr = res->start; - hdmi->qfprom_mmio = msm_ioremap(pdev, - config->qfprom_mmio_name, "HDMI_QFPROM"); + hdmi->qfprom_mmio = msm_ioremap(pdev, config->qfprom_mmio_name); if (IS_ERR(hdmi->qfprom_mmio)) { DRM_DEV_INFO(&pdev->dev, "can't find qfprom resource\n"); hdmi->qfprom_mmio = NULL; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c index 16b0e8836d275..9780107e1cc97 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c @@ -144,7 +144,7 @@ static int msm_hdmi_phy_probe(struct platform_device *pdev) if (!phy->cfg) return -ENODEV; - phy->mmio = msm_ioremap(pdev, "hdmi_phy", "HDMI_PHY"); + phy->mmio = msm_ioremap(pdev, "hdmi_phy"); if (IS_ERR(phy->mmio)) { DRM_DEV_ERROR(dev, "%s: failed to map phy base\n", __func__); return -ENOMEM; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c index 99c7853353fd6..b06d9d25a1894 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c @@ -716,19 +716,18 @@ int msm_hdmi_pll_8996_init(struct platform_device *pdev) pll->pdev = pdev; - pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll", "HDMI_PLL"); + pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll"); if (IS_ERR(pll->mmio_qserdes_com)) { DRM_DEV_ERROR(dev, "failed to map pll base\n"); return -ENOMEM; } for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) { - char name[32], label[32]; + char name[32]; snprintf(name, sizeof(name), "hdmi_tx_l%d", i); - snprintf(label, sizeof(label), "HDMI_TX_L%d", i); - pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name, label); + pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name); if (IS_ERR(pll->mmio_qserdes_tx[i])) { DRM_DEV_ERROR(dev, "failed to map pll base\n"); return -ENOMEM; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c b/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c index 562dfac677929..be4b0b67e797a 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c @@ -434,7 +434,7 @@ int msm_hdmi_pll_8960_init(struct platform_device *pdev) if (!pll) return -ENOMEM; - pll->mmio = msm_ioremap(pdev, "hdmi_pll", "HDMI_PLL"); + pll->mmio = msm_ioremap(pdev, "hdmi_pll"); if (IS_ERR(pll->mmio)) { DRM_DEV_ERROR(dev, "failed to map pll base\n"); return -ENOMEM; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 1145e06513df5..4445025a6c4b9 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -116,7 +116,7 @@ struct clk *msm_clk_get(struct platform_device *pdev, const char *name) } static void __iomem *_msm_ioremap(struct platform_device *pdev, const char *name, - const char *dbgname, bool quiet, phys_addr_t *psize) + bool quiet, phys_addr_t *psize) { struct resource *res; unsigned long size; @@ -148,22 +148,20 @@ static void __iomem *_msm_ioremap(struct platform_device *pdev, const char *name return ptr; } -void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, - const char *dbgname) +void __iomem *msm_ioremap(struct platform_device *pdev, const char *name) { - return _msm_ioremap(pdev, name, dbgname, false, NULL); + return _msm_ioremap(pdev, name, false, NULL); } -void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name, - const char *dbgname) +void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name) { - return _msm_ioremap(pdev, name, dbgname, true, NULL); + return _msm_ioremap(pdev, name, true, NULL); } void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name, - const char *dbgname, phys_addr_t *psize) + phys_addr_t *psize) { - return _msm_ioremap(pdev, name, dbgname, false, psize); + return _msm_ioremap(pdev, name, false, psize); } void msm_writel(u32 data, void __iomem *addr) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index d7574e6bd4e40..56d1242efcc1f 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -480,12 +480,10 @@ struct clk *msm_clk_get(struct platform_device *pdev, const char *name); struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count, const char *name); -void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, - const char *dbgname); +void __iomem *msm_ioremap(struct platform_device *pdev, const char *name); void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name, - const char *dbgname, phys_addr_t *size); -void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name, - const char *dbgname); + phys_addr_t *size); +void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name); void msm_writel(u32 data, void __iomem *addr); u32 msm_readl(const void __iomem *addr); void msm_rmw(void __iomem *addr, u32 mask, u32 or); diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 2c1049c0ea14c..998e705c15efa 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -861,7 +861,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, /* Map registers: */ - gpu->mmio = msm_ioremap(pdev, config->ioname, name); + gpu->mmio = msm_ioremap(pdev, config->ioname); if (IS_ERR(gpu->mmio)) { ret = PTR_ERR(gpu->mmio); goto fail; From 3f4a80cbf968466c5ba0c78ef41cae8292965bd8 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 6 Jan 2022 02:27:00 +0300 Subject: [PATCH 04/70] drm/msm: move msm_readl/_writel to msm_drv.h With the reglog removal, msm_readl/_writel became single line wrappers around readl/writel. Move those two wrappers and msm_rmw to msm_drv.h to remove need for extra function calls when doing register writes. Signed-off-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20220105232700.444170-3-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/msm_drv.c | 20 -------------------- drivers/gpu/drm/msm/msm_drv.h | 14 +++++++++++--- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 4445025a6c4b9..68524e3a11138 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -164,26 +164,6 @@ void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name, return _msm_ioremap(pdev, name, false, psize); } -void msm_writel(u32 data, void __iomem *addr) -{ - writel(data, addr); -} - -u32 msm_readl(const void __iomem *addr) -{ - u32 val = readl(addr); - - return val; -} - -void msm_rmw(void __iomem *addr, u32 mask, u32 or) -{ - u32 val = msm_readl(addr); - - val &= ~mask; - msm_writel(val | or, addr); -} - static enum hrtimer_restart msm_hrtimer_worktimer(struct hrtimer *t) { struct msm_hrtimer_work *work = container_of(t, diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 56d1242efcc1f..3ab19775a5c37 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -484,9 +484,17 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name); void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name, phys_addr_t *size); void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name); -void msm_writel(u32 data, void __iomem *addr); -u32 msm_readl(const void __iomem *addr); -void msm_rmw(void __iomem *addr, u32 mask, u32 or); + +#define msm_writel(data, addr) writel((data), (addr)) +#define msm_readl(addr) readl((addr)) + +static inline void msm_rmw(void __iomem *addr, u32 mask, u32 or) +{ + u32 val = msm_readl(addr); + + val &= ~mask; + msm_writel(val | or, addr); +} /** * struct msm_hrtimer_work - a helper to combine an hrtimer with kthread_work From b00e53f548ff6fbf66b096c6e6fa8352c61d9237 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 6 Jan 2022 10:06:56 +0300 Subject: [PATCH 05/70] drm/msm: reduce usage of round_pixclk callback The round_pixclk() callback returns different rate only on MDP4 in HDMI (DTV) case. Stop using this callback in other cases to simplify mode_valid callbacks. Signed-off-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220106070656.482882-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 7 ------- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 7 ------- drivers/gpu/drm/msm/dsi/dsi_manager.c | 22 ---------------------- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 11 +++++++---- 4 files changed, 7 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 201c0e3082ddb..3eba70c06e3c5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -774,12 +774,6 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms) return ret; } -static long dpu_kms_round_pixclk(struct msm_kms *kms, unsigned long rate, - struct drm_encoder *encoder) -{ - return rate; -} - static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) { int i; @@ -948,7 +942,6 @@ static const struct msm_kms_funcs kms_funcs = { .disable_vblank = dpu_kms_disable_vblank, .check_modified_format = dpu_format_check_modified_format, .get_format = dpu_get_msm_format, - .round_pixclk = dpu_kms_round_pixclk, .destroy = dpu_kms_destroy, .snapshot = dpu_kms_mdp_snapshot, #ifdef CONFIG_DEBUG_FS diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 81bd434980cfe..3b92372e7bdf1 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -190,12 +190,6 @@ static void mdp5_complete_commit(struct msm_kms *kms, unsigned crtc_mask) mdp5_smp_complete_commit(mdp5_kms->smp, &global_state->smp); } -static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate, - struct drm_encoder *encoder) -{ - return rate; -} - static int mdp5_set_split_display(struct msm_kms *kms, struct drm_encoder *encoder, struct drm_encoder *slave_encoder, @@ -278,7 +272,6 @@ static const struct mdp_kms_funcs kms_funcs = { .wait_flush = mdp5_wait_flush, .complete_commit = mdp5_complete_commit, .get_format = mdp_get_format, - .round_pixclk = mdp5_round_pixclk, .set_split_display = mdp5_set_split_display, .destroy = mdp5_kms_destroy, #ifdef CONFIG_DEBUG_FS diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index f19bae475c966..1dbbfca163d99 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -305,27 +305,6 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector) return num; } -static enum drm_mode_status dsi_mgr_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - int id = dsi_mgr_connector_get_id(connector); - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - struct drm_encoder *encoder = msm_dsi_get_encoder(msm_dsi); - struct msm_drm_private *priv = connector->dev->dev_private; - struct msm_kms *kms = priv->kms; - long actual, requested; - - DBG(""); - requested = 1000 * mode->clock; - actual = kms->funcs->round_pixclk(kms, requested, encoder); - - DBG("requested=%ld, actual=%ld", requested, actual); - if (actual != requested) - return MODE_CLOCK_RANGE; - - return MODE_OK; -} - static struct drm_encoder * dsi_mgr_connector_best_encoder(struct drm_connector *connector) { @@ -586,7 +565,6 @@ static const struct drm_connector_funcs dsi_mgr_connector_funcs = { static const struct drm_connector_helper_funcs dsi_mgr_conn_helper_funcs = { .get_modes = dsi_mgr_connector_get_modes, - .mode_valid = dsi_mgr_connector_mode_valid, .best_encoder = dsi_mgr_connector_best_encoder, }; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 68fba4bf72121..10ebe2089cb61 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -282,15 +282,18 @@ static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge long actual, requested; requested = 1000 * mode->clock; - actual = kms->funcs->round_pixclk(kms, - requested, hdmi_bridge->hdmi->encoder); /* for mdp5/apq8074, we manage our own pixel clk (as opposed to * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder * instead): */ - if (config->pwr_clk_cnt > 0) - actual = clk_round_rate(hdmi->pwr_clks[0], actual); + if (kms->funcs->round_pixclk) + actual = kms->funcs->round_pixclk(kms, + requested, hdmi_bridge->hdmi->encoder); + else if (config->pwr_clk_cnt > 0) + actual = clk_round_rate(hdmi->pwr_clks[0], requested); + else + actual = requested; DBG("requested=%ld, actual=%ld", requested, actual); From cfdc428d81a06d1b14dcbbe7aad285e076c9b917 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 14 Jan 2022 10:57:42 -0800 Subject: [PATCH 06/70] drm/msm/rd: Add chip-id For newer devices which deprecate gpu-id and do matching based on chip-id, we need this information in cmdstream dumps so that the decoding tools know how to decode them. Signed-off-by: Rob Clark Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220114185742.283539-1-robdclark@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/msm_rd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c index 81432ec070124..7e4d6460719eb 100644 --- a/drivers/gpu/drm/msm/msm_rd.c +++ b/drivers/gpu/drm/msm/msm_rd.c @@ -62,6 +62,7 @@ enum rd_sect_type { RD_FRAG_SHADER, RD_BUFFER_CONTENTS, RD_GPU_ID, + RD_CHIP_ID, }; #define BUF_SZ 512 /* should be power of 2 */ @@ -202,6 +203,9 @@ static int rd_open(struct inode *inode, struct file *file) rd_write_section(rd, RD_GPU_ID, &gpu_id, sizeof(gpu_id)); + gpu->funcs->get_param(gpu, MSM_PARAM_CHIP_ID, &val); + rd_write_section(rd, RD_CHIP_ID, &val, sizeof(val)); + out: mutex_unlock(&gpu->lock); return ret; From d89e5028346bd80f79c3073d132123e7a17e1177 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 20 Jan 2022 01:16:14 +0300 Subject: [PATCH 07/70] drm/msm: move utility functions from msm_drv.c Move clock/IO/hrtimer utility functions from msm_drv.c to new msm_io_utils.c file. Signed-off-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Link: https://lore.kernel.org/r/20220119221616.3089119-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/msm_drv.c | 118 --------------------------- drivers/gpu/drm/msm/msm_io_utils.c | 126 +++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 118 deletions(-) create mode 100644 drivers/gpu/drm/msm/msm_io_utils.c diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 03ab55c37beb6..5b6e37477079a 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -87,6 +87,7 @@ msm-y := \ msm_gem_vma.o \ msm_gpu.o \ msm_gpu_devfreq.o \ + msm_io_utils.o \ msm_iommu.o \ msm_perf.o \ msm_rd.o \ diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 68524e3a11138..d1bad842fcf2e 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -75,124 +75,6 @@ static bool modeset = true; MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (1=on (default), 0=disable)"); module_param(modeset, bool, 0600); -/* - * Util/helpers: - */ - -struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count, - const char *name) -{ - int i; - char n[32]; - - snprintf(n, sizeof(n), "%s_clk", name); - - for (i = 0; bulk && i < count; i++) { - if (!strcmp(bulk[i].id, name) || !strcmp(bulk[i].id, n)) - return bulk[i].clk; - } - - - return NULL; -} - -struct clk *msm_clk_get(struct platform_device *pdev, const char *name) -{ - struct clk *clk; - char name2[32]; - - clk = devm_clk_get(&pdev->dev, name); - if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER) - return clk; - - snprintf(name2, sizeof(name2), "%s_clk", name); - - clk = devm_clk_get(&pdev->dev, name2); - if (!IS_ERR(clk)) - dev_warn(&pdev->dev, "Using legacy clk name binding. Use " - "\"%s\" instead of \"%s\"\n", name, name2); - - return clk; -} - -static void __iomem *_msm_ioremap(struct platform_device *pdev, const char *name, - bool quiet, phys_addr_t *psize) -{ - struct resource *res; - unsigned long size; - void __iomem *ptr; - - if (name) - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); - else - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - if (!res) { - if (!quiet) - DRM_DEV_ERROR(&pdev->dev, "failed to get memory resource: %s\n", name); - return ERR_PTR(-EINVAL); - } - - size = resource_size(res); - - ptr = devm_ioremap(&pdev->dev, res->start, size); - if (!ptr) { - if (!quiet) - DRM_DEV_ERROR(&pdev->dev, "failed to ioremap: %s\n", name); - return ERR_PTR(-ENOMEM); - } - - if (psize) - *psize = size; - - return ptr; -} - -void __iomem *msm_ioremap(struct platform_device *pdev, const char *name) -{ - return _msm_ioremap(pdev, name, false, NULL); -} - -void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name) -{ - return _msm_ioremap(pdev, name, true, NULL); -} - -void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name, - phys_addr_t *psize) -{ - return _msm_ioremap(pdev, name, false, psize); -} - -static enum hrtimer_restart msm_hrtimer_worktimer(struct hrtimer *t) -{ - struct msm_hrtimer_work *work = container_of(t, - struct msm_hrtimer_work, timer); - - kthread_queue_work(work->worker, &work->work); - - return HRTIMER_NORESTART; -} - -void msm_hrtimer_queue_work(struct msm_hrtimer_work *work, - ktime_t wakeup_time, - enum hrtimer_mode mode) -{ - hrtimer_start(&work->timer, wakeup_time, mode); -} - -void msm_hrtimer_work_init(struct msm_hrtimer_work *work, - struct kthread_worker *worker, - kthread_work_func_t fn, - clockid_t clock_id, - enum hrtimer_mode mode) -{ - hrtimer_init(&work->timer, clock_id, mode); - work->timer.function = msm_hrtimer_worktimer; - work->worker = worker; - kthread_init_work(&work->work, fn); -} - static irqreturn_t msm_irq(int irq, void *arg) { struct drm_device *dev = arg; diff --git a/drivers/gpu/drm/msm/msm_io_utils.c b/drivers/gpu/drm/msm/msm_io_utils.c new file mode 100644 index 0000000000000..7b504617833ad --- /dev/null +++ b/drivers/gpu/drm/msm/msm_io_utils.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2018, 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (C) 2013 Red Hat + * Author: Rob Clark + */ + +#include "msm_drv.h" + +/* + * Util/helpers: + */ + +struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count, + const char *name) +{ + int i; + char n[32]; + + snprintf(n, sizeof(n), "%s_clk", name); + + for (i = 0; bulk && i < count; i++) { + if (!strcmp(bulk[i].id, name) || !strcmp(bulk[i].id, n)) + return bulk[i].clk; + } + + + return NULL; +} + +struct clk *msm_clk_get(struct platform_device *pdev, const char *name) +{ + struct clk *clk; + char name2[32]; + + clk = devm_clk_get(&pdev->dev, name); + if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER) + return clk; + + snprintf(name2, sizeof(name2), "%s_clk", name); + + clk = devm_clk_get(&pdev->dev, name2); + if (!IS_ERR(clk)) + dev_warn(&pdev->dev, "Using legacy clk name binding. Use " + "\"%s\" instead of \"%s\"\n", name, name2); + + return clk; +} + +static void __iomem *_msm_ioremap(struct platform_device *pdev, const char *name, + bool quiet, phys_addr_t *psize) +{ + struct resource *res; + unsigned long size; + void __iomem *ptr; + + if (name) + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); + else + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!res) { + if (!quiet) + DRM_DEV_ERROR(&pdev->dev, "failed to get memory resource: %s\n", name); + return ERR_PTR(-EINVAL); + } + + size = resource_size(res); + + ptr = devm_ioremap(&pdev->dev, res->start, size); + if (!ptr) { + if (!quiet) + DRM_DEV_ERROR(&pdev->dev, "failed to ioremap: %s\n", name); + return ERR_PTR(-ENOMEM); + } + + if (psize) + *psize = size; + + return ptr; +} + +void __iomem *msm_ioremap(struct platform_device *pdev, const char *name) +{ + return _msm_ioremap(pdev, name, false, NULL); +} + +void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name) +{ + return _msm_ioremap(pdev, name, true, NULL); +} + +void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name, + phys_addr_t *psize) +{ + return _msm_ioremap(pdev, name, false, psize); +} + +static enum hrtimer_restart msm_hrtimer_worktimer(struct hrtimer *t) +{ + struct msm_hrtimer_work *work = container_of(t, + struct msm_hrtimer_work, timer); + + kthread_queue_work(work->worker, &work->work); + + return HRTIMER_NORESTART; +} + +void msm_hrtimer_queue_work(struct msm_hrtimer_work *work, + ktime_t wakeup_time, + enum hrtimer_mode mode) +{ + hrtimer_start(&work->timer, wakeup_time, mode); +} + +void msm_hrtimer_work_init(struct msm_hrtimer_work *work, + struct kthread_worker *worker, + kthread_work_func_t fn, + clockid_t clock_id, + enum hrtimer_mode mode) +{ + hrtimer_init(&work->timer, clock_id, mode); + work->timer.function = msm_hrtimer_worktimer; + work->worker = worker; + kthread_init_work(&work->work, fn); +} From 3d18c34d84b4119fd42db3d68b79d1d3a6d53f0b Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 15 Oct 2021 16:17:02 -0700 Subject: [PATCH 08/70] drm/msm/dp: Move debugfs files into subdirectory In the cleanup path of the MSM DP driver the DP driver's debugfs files are destroyed by invoking debugfs_remove_recursive() on debug->root, which during initialization has been set to minor->debugfs_root. To allow cleaning up the DP driver's debugfs files either each dentry needs to be kept track of or the files needs to be put in a subdirectory which can be removed in one go. By choosing to put the debugfs files in a subdirectory, based on the name of the associated connector this also solves the problem that these names would collide as support for multiple DP instances are introduced. One alternative solution to the problem with colliding file names would have been to put keep track of the individual files and put them under the connector's debugfs directory. But while the drm_connector has been allocated, its associated debugfs directory has not been created at the time of initialization of the dp_debug. Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20211015231702.1784254-1-bjorn.andersson@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_debug.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index da4323556ef30..67da4c69eca1b 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -210,26 +210,29 @@ static const struct file_operations test_active_fops = { static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) { int rc = 0; + char path[64]; struct dp_debug_private *debug = container_of(dp_debug, struct dp_debug_private, dp_debug); - debugfs_create_file("dp_debug", 0444, minor->debugfs_root, + snprintf(path, sizeof(path), "msm_dp-%s", debug->connector->name); + + debug->root = debugfs_create_dir(path, minor->debugfs_root); + + debugfs_create_file("dp_debug", 0444, debug->root, debug, &dp_debug_fops); debugfs_create_file("msm_dp_test_active", 0444, - minor->debugfs_root, + debug->root, debug, &test_active_fops); debugfs_create_file("msm_dp_test_data", 0444, - minor->debugfs_root, + debug->root, debug, &dp_test_data_fops); debugfs_create_file("msm_dp_test_type", 0444, - minor->debugfs_root, + debug->root, debug, &dp_test_type_fops); - debug->root = minor->debugfs_root; - return rc; } From 74222b7c4214c9bfb915508ad4691d9127555ef5 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 16 Dec 2021 16:26:43 -0800 Subject: [PATCH 09/70] drm/msm/dp: Add sc8180x DP controllers The sc8180x has 2 DP and 1 eDP controllers, add support for these to the DP driver. Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20211217002643.2305526-1-bjorn.andersson@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_display.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 7cc4d21f20911..cab026d27f424 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -143,10 +143,21 @@ static const struct msm_dp_config sc7280_dp_cfg = { .num_descs = 2, }; +static const struct msm_dp_config sc8180x_dp_cfg = { + .descs = (const struct msm_dp_desc[]) { + [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, + [MSM_DP_CONTROLLER_1] = { .io_start = 0x0ae98000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, + [MSM_DP_CONTROLLER_2] = { .io_start = 0x0ae9a000, .connector_type = DRM_MODE_CONNECTOR_eDP }, + }, + .num_descs = 3, +}; + static const struct of_device_id dp_dt_match[] = { { .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_cfg }, { .compatible = "qcom,sc7280-dp", .data = &sc7280_dp_cfg }, { .compatible = "qcom,sc7280-edp", .data = &sc7280_dp_cfg }, + { .compatible = "qcom,sc8180x-dp", .data = &sc8180x_dp_cfg }, + { .compatible = "qcom,sc8180x-edp", .data = &sc8180x_dp_cfg }, {} }; From 31e0889daa4b8fcfd785a71b5f323015d67ad037 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Wed, 22 Dec 2021 20:33:47 +0100 Subject: [PATCH 10/70] drm/msm/dp: Simplify dp_debug_init() and dp_debug_get() dp_debug_init() always returns 0. So, make it a void function and simplify the only caller accordingly. While at it remove a useless 'rc' initialization in dp_debug_get() Signed-off-by: Christophe JAILLET Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/dc2d6f535379dd38a5e3f9ba502f1f2b3d1f56b7.1640201523.git.christophe.jaillet@wanadoo.fr Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_debug.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 67da4c69eca1b..2f9c943f12d56 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -207,9 +207,8 @@ static const struct file_operations test_active_fops = { .write = dp_test_active_write }; -static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) +static void dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) { - int rc = 0; char path[64]; struct dp_debug_private *debug = container_of(dp_debug, struct dp_debug_private, dp_debug); @@ -232,17 +231,15 @@ static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) debugfs_create_file("msm_dp_test_type", 0444, debug->root, debug, &dp_test_type_fops); - - return rc; } struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, struct dp_usbpd *usbpd, struct dp_link *link, struct drm_connector *connector, struct drm_minor *minor) { - int rc = 0; struct dp_debug_private *debug; struct dp_debug *dp_debug; + int rc; if (!dev || !panel || !usbpd || !link) { DRM_ERROR("invalid input\n"); @@ -269,11 +266,7 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, dp_debug->hdisplay = 0; dp_debug->vrefresh = 0; - rc = dp_debug_init(dp_debug, minor); - if (rc) { - devm_kfree(dev, debug); - goto error; - } + dp_debug_init(dp_debug, minor); return dp_debug; error: From f5408b21e356f2b57efcb3e2dbb5a344a20d11ae Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 27 Dec 2021 20:59:34 -0800 Subject: [PATCH 11/70] drm/msm/dp: Add DisplayPort controller for SM8350 The Qualcomm SM8350 platform comes with a single DisplayPort controller, add support for this in the DisplayPort driver. Signed-off-by: Bjorn Andersson Acked-by: Rob Herring Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20211228045934.1524865-1-bjorn.andersson@linaro.org Signed-off-by: Dmitry Baryshkov --- .../devicetree/bindings/display/msm/dp-controller.yaml | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 5457612ab1363..cd05cfd765362 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -21,6 +21,7 @@ properties: - qcom,sc7280-edp - qcom,sc8180x-dp - qcom,sc8180x-edp + - qcom,sm8350-dp reg: items: diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index cab026d27f424..5ae81d2f2862d 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -152,12 +152,20 @@ static const struct msm_dp_config sc8180x_dp_cfg = { .num_descs = 3, }; +static const struct msm_dp_config sm8350_dp_cfg = { + .descs = (const struct msm_dp_desc[]) { + [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, + }, + .num_descs = 1, +}; + static const struct of_device_id dp_dt_match[] = { { .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_cfg }, { .compatible = "qcom,sc7280-dp", .data = &sc7280_dp_cfg }, { .compatible = "qcom,sc7280-edp", .data = &sc7280_dp_cfg }, { .compatible = "qcom,sc8180x-dp", .data = &sc8180x_dp_cfg }, { .compatible = "qcom,sc8180x-edp", .data = &sc8180x_dp_cfg }, + { .compatible = "qcom,sm8350-dp", .data = &sm8350_dp_cfg }, {} }; From 989ebe7bc4463002c210db0010c8475797a9098f Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Tue, 18 Jan 2022 10:47:25 -0800 Subject: [PATCH 12/70] drm/msm/dp: do not initialize phy until plugin interrupt received Current DP drivers have regulators, clocks, irq and phy are grouped together within a function and executed not in a symmetric manner. This increase difficulty of code maintenance and limited code scalability. This patch divides the driver life cycle of operation into four states, resume (including booting up), dongle plugin, dongle unplugged and suspend. Regulators, core clocks and irq are grouped together and enabled at resume (or booting up) so that the DP controller is armed and ready to receive HPD plugin interrupts. HPD plugin interrupt is generated when a dongle plugs into DUT (device under test). Once HPD plugin interrupt is received, DP controller will initialize phy so that dpcd read/write will function and following link training can be proceeded successfully. DP phy will be disabled after main link is teared down at end of unplugged HPD interrupt handle triggered by dongle unplugged out of DUT. Finally regulators, code clocks and irq are disabled at corresponding suspension. Changes in V2: -- removed unnecessary dp_ctrl NULL check -- removed unnecessary phy init_count and power_count DRM_DEBUG_DP logs -- remove flip parameter out of dp_ctrl_irq_enable() -- add fixes tag Changes in V3: -- call dp_display_host_phy_init() instead of dp_ctrl_phy_init() at dp_display_host_init() for eDP Changes in V4: -- rewording commit text to match this commit changes Changes in V5: -- rebase on top of msm-next branch Changes in V6: -- delete flip variable Changes in V7: -- dp_ctrl_irq_enable/disabe() merged into dp_ctrl_reset_irq_ctrl() Changes in V8: -- add more detail comment regrading dp phy at dp_display_host_init() Changes in V9: -- remove set phy_initialized to false when -ECONNRESET detected Changes in v10: -- group into one series Changes in v11: -- drop drm/msm/dp: dp_link_parse_sink_count() return immediately if aux read Changes in v12: -- move dp_display_host_phy_exit() after dp_display_host_deinit() Changes in v13: -- do not execute phy_init until plugged_in interrupt for edp, same as DP. Changes in v14: -- remove redundant dp->core_initialized = false form dp_pm_suspend. Changes in v15: -- remove core_initialized flag check at both host_init and host_deinit Changes in v16: -- remove dp_display_host_phy_exit core_initialized=false at dp_pm_suspend Changes in v17: -- remove core_initialized checking before execute attention_cb() Changes in v18: -- remove core_initialized checking at dp_pm_suspend Fixes: 8ede2ecc3e5e ("drm/msm/dp: Add DP compliance tests on Snapdragon Chipsets") Signed-off-by: Kuogee Hsieh Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/1642531648-8448-2-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 80 ++++++++------------ drivers/gpu/drm/msm/dp/dp_ctrl.h | 8 +- drivers/gpu/drm/msm/dp/dp_display.c | 111 ++++++++++++++-------------- 3 files changed, 92 insertions(+), 107 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index c724cb0bde9dc..9c80b493f974a 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1365,60 +1365,44 @@ static int dp_ctrl_enable_stream_clocks(struct dp_ctrl_private *ctrl) return ret; } -int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset) +void dp_ctrl_reset_irq_ctrl(struct dp_ctrl *dp_ctrl, bool enable) +{ + struct dp_ctrl_private *ctrl; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + dp_catalog_ctrl_reset(ctrl->catalog); + + if (enable) + dp_catalog_ctrl_enable_irq(ctrl->catalog, enable); +} + +void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; struct dp_io *dp_io; struct phy *phy; - if (!dp_ctrl) { - DRM_ERROR("Invalid input data\n"); - return -EINVAL; - } - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); dp_io = &ctrl->parser->io; phy = dp_io->phy; - ctrl->dp_ctrl.orientation = flip; - - if (reset) - dp_catalog_ctrl_reset(ctrl->catalog); - - DRM_DEBUG_DP("flip=%d\n", flip); dp_catalog_ctrl_phy_reset(ctrl->catalog); phy_init(phy); - dp_catalog_ctrl_enable_irq(ctrl->catalog, true); - - return 0; } -/** - * dp_ctrl_host_deinit() - Uninitialize DP controller - * @dp_ctrl: Display Port Driver data - * - * Perform required steps to uninitialize DP controller - * and its resources. - */ -void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl) +void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; struct dp_io *dp_io; struct phy *phy; - if (!dp_ctrl) { - DRM_ERROR("Invalid input data\n"); - return; - } - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); dp_io = &ctrl->parser->io; phy = dp_io->phy; - dp_catalog_ctrl_enable_irq(ctrl->catalog, false); + dp_catalog_ctrl_phy_reset(ctrl->catalog); phy_exit(phy); - - DRM_DEBUG_DP("Host deinitialized successfully\n"); } static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl) @@ -1488,7 +1472,10 @@ static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl) } phy_power_off(phy); + + /* aux channel down, reinit phy */ phy_exit(phy); + phy_init(phy); return 0; } @@ -1893,8 +1880,14 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) return ret; } + DRM_DEBUG_DP("Before, phy=%x init_count=%d power_on=%d\n", + (u32)(uintptr_t)phy, phy->init_count, phy->power_count); + phy_power_off(phy); + DRM_DEBUG_DP("After, phy=%x init_count=%d power_on=%d\n", + (u32)(uintptr_t)phy, phy->init_count, phy->power_count); + /* aux channel down, reinit phy */ phy_exit(phy); phy_init(phy); @@ -1903,23 +1896,6 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) return ret; } -void dp_ctrl_off_phy(struct dp_ctrl *dp_ctrl) -{ - struct dp_ctrl_private *ctrl; - struct dp_io *dp_io; - struct phy *phy; - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - dp_io = &ctrl->parser->io; - phy = dp_io->phy; - - dp_catalog_ctrl_reset(ctrl->catalog); - - phy_exit(phy); - - DRM_DEBUG_DP("DP off phy done\n"); -} - int dp_ctrl_off(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; @@ -1947,10 +1923,14 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl) DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); } + DRM_DEBUG_DP("Before, phy=%x init_count=%d power_on=%d\n", + (u32)(uintptr_t)phy, phy->init_count, phy->power_count); + phy_power_off(phy); - phy_exit(phy); - DRM_DEBUG_DP("DP off done\n"); + DRM_DEBUG_DP("After, phy=%x init_count=%d power_on=%d\n", + (u32)(uintptr_t)phy, phy->init_count, phy->power_count); + return ret; } diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 2363a2df9597b..2433edbc70a6d 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -19,12 +19,9 @@ struct dp_ctrl { u32 pixel_rate; }; -int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset); -void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl); int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl); int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl); int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl); -void dp_ctrl_off_phy(struct dp_ctrl *dp_ctrl); int dp_ctrl_off(struct dp_ctrl *dp_ctrl); void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl); void dp_ctrl_isr(struct dp_ctrl *dp_ctrl); @@ -34,4 +31,9 @@ struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, struct dp_power *power, struct dp_catalog *catalog, struct dp_parser *parser); +void dp_ctrl_reset_irq_ctrl(struct dp_ctrl *dp_ctrl, bool enable); +void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl); +void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl); +void dp_ctrl_irq_phy_exit(struct dp_ctrl *dp_ctrl); + #endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 5ae81d2f2862d..faf542ce49fa9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -83,6 +83,7 @@ struct dp_display_private { /* state variables */ bool core_initialized; + bool phy_initialized; bool hpd_irq_on; bool audio_supported; @@ -391,36 +392,45 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) return rc; } -static void dp_display_host_init(struct dp_display_private *dp, int reset) +static void dp_display_host_phy_init(struct dp_display_private *dp) { - bool flip = false; + DRM_DEBUG_DP("core_init=%d phy_init=%d\n", + dp->core_initialized, dp->phy_initialized); - DRM_DEBUG_DP("core_initialized=%d\n", dp->core_initialized); - if (dp->core_initialized) { - DRM_DEBUG_DP("DP core already initialized\n"); - return; + if (!dp->phy_initialized) { + dp_ctrl_phy_init(dp->ctrl); + dp->phy_initialized = true; } +} + +static void dp_display_host_phy_exit(struct dp_display_private *dp) +{ + DRM_DEBUG_DP("core_init=%d phy_init=%d\n", + dp->core_initialized, dp->phy_initialized); - if (dp->usbpd->orientation == ORIENTATION_CC2) - flip = true; + if (dp->phy_initialized) { + dp_ctrl_phy_exit(dp->ctrl); + dp->phy_initialized = false; + } +} + +static void dp_display_host_init(struct dp_display_private *dp) +{ + DRM_DEBUG_DP("core_initialized=%d\n", dp->core_initialized); - dp_power_init(dp->power, flip); - dp_ctrl_host_init(dp->ctrl, flip, reset); + dp_power_init(dp->power, false); + dp_ctrl_reset_irq_ctrl(dp->ctrl, true); dp_aux_init(dp->aux); dp->core_initialized = true; } static void dp_display_host_deinit(struct dp_display_private *dp) { - if (!dp->core_initialized) { - DRM_DEBUG_DP("DP core not initialized\n"); - return; - } + DRM_DEBUG_DP("core_initialized=%d\n", dp->core_initialized); - dp_ctrl_host_deinit(dp->ctrl); + dp_ctrl_reset_irq_ctrl(dp->ctrl, false); dp_aux_deinit(dp->aux); dp_power_deinit(dp->power); - dp->core_initialized = false; } @@ -428,7 +438,7 @@ static int dp_display_usbpd_configure_cb(struct device *dev) { struct dp_display_private *dp = dev_get_dp_display_private(dev); - dp_display_host_init(dp, false); + dp_display_host_phy_init(dp); return dp_display_process_hpd_high(dp); } @@ -549,11 +559,6 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) ret = dp_display_usbpd_configure_cb(&dp->pdev->dev); if (ret) { /* link train failed */ dp->hpd_state = ST_DISCONNECTED; - - if (ret == -ECONNRESET) { /* cable unplugged */ - dp->core_initialized = false; - } - } else { /* start sentinel checking in case of missing uevent */ dp_add_event(dp, EV_CONNECT_PENDING_TIMEOUT, 0, tout); @@ -623,8 +628,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) if (state == ST_DISCONNECTED) { /* triggered by irq_hdp with sink_count = 0 */ if (dp->link->sink_count == 0) { - dp_ctrl_off_phy(dp->ctrl); - dp->core_initialized = false; + dp_display_host_phy_exit(dp); } mutex_unlock(&dp->event_mutex); return 0; @@ -686,7 +690,6 @@ static int dp_disconnect_pending_timeout(struct dp_display_private *dp, u32 data static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) { u32 state; - int ret; mutex_lock(&dp->event_mutex); @@ -711,16 +714,8 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) return 0; } - /* - * dp core (ahb/aux clks) must be initialized before - * irq_hpd be handled - */ - if (dp->core_initialized) { - ret = dp_display_usbpd_attention_cb(&dp->pdev->dev); - if (ret == -ECONNRESET) { /* cable unplugged */ - dp->core_initialized = false; - } - } + dp_display_usbpd_attention_cb(&dp->pdev->dev); + DRM_DEBUG_DP("hpd_state=%d\n", state); mutex_unlock(&dp->event_mutex); @@ -911,12 +906,19 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data) dp_display->audio_enabled = false; - /* triggered by irq_hpd with sink_count = 0 */ if (dp->link->sink_count == 0) { + /* + * irq_hpd with sink_count = 0 + * hdmi unplugged out of dongle + */ dp_ctrl_off_link_stream(dp->ctrl); } else { + /* + * unplugged interrupt + * dongle unplugged out of DUT + */ dp_ctrl_off(dp->ctrl); - dp->core_initialized = false; + dp_display_host_phy_exit(dp); } dp_display->power_on = false; @@ -1046,7 +1048,7 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp) static void dp_display_config_hpd(struct dp_display_private *dp) { - dp_display_host_init(dp, true); + dp_display_host_init(dp); dp_catalog_ctrl_hpd_config(dp->catalog); /* Enable interrupt first time @@ -1325,20 +1327,23 @@ static int dp_pm_resume(struct device *dev) dp->hpd_state = ST_DISCONNECTED; /* turn on dp ctrl/phy */ - dp_display_host_init(dp, true); + dp_display_host_init(dp); dp_catalog_ctrl_hpd_config(dp->catalog); - /* - * set sink to normal operation mode -- D0 - * before dpcd read - */ - dp_link_psm_config(dp->link, &dp->panel->link_info, false); if (dp_catalog_link_is_connected(dp->catalog)) { + /* + * set sink to normal operation mode -- D0 + * before dpcd read + */ + dp_display_host_phy_init(dp); + dp_link_psm_config(dp->link, &dp->panel->link_info, false); sink_count = drm_dp_read_sink_count(dp->aux); if (sink_count < 0) sink_count = 0; + + dp_display_host_phy_exit(dp); } dp->link->sink_count = sink_count; @@ -1377,18 +1382,16 @@ static int dp_pm_suspend(struct device *dev) DRM_DEBUG_DP("Before, core_inited=%d power_on=%d\n", dp->core_initialized, dp_display->power_on); - if (dp->core_initialized == true) { - /* mainlink enabled */ - if (dp_power_clk_status(dp->power, DP_CTRL_PM)) - dp_ctrl_off_link_stream(dp->ctrl); + /* mainlink enabled */ + if (dp_power_clk_status(dp->power, DP_CTRL_PM)) + dp_ctrl_off_link_stream(dp->ctrl); - dp_display_host_deinit(dp); - } - - dp->hpd_state = ST_SUSPENDED; + dp_display_host_phy_exit(dp); /* host_init will be called at pm_resume */ - dp->core_initialized = false; + dp_display_host_deinit(dp); + + dp->hpd_state = ST_SUSPENDED; DRM_DEBUG_DP("After, core_inited=%d power_on=%d\n", dp->core_initialized, dp_display->power_on); @@ -1554,7 +1557,7 @@ int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder) state = dp_display->hpd_state; if (state == ST_DISPLAY_OFF) - dp_display_host_init(dp_display, true); + dp_display_host_phy_init(dp_display); dp_display_enable(dp_display, 0); From 5e602f5156910c7b19661699896cb6e3fb94fab9 Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Tue, 18 Jan 2022 10:47:26 -0800 Subject: [PATCH 13/70] drm/msm/dp: populate connector of struct dp_panel DP CTS test case 4.2.2.6 has valid edid with bad checksum on purpose and expect DP source return correct checksum. During drm edid read, correct edid checksum is calculated and stored at connector::real_edid_checksum. The problem is struct dp_panel::connector never be assigned, instead the connector is stored in struct msm_dp::connector. When we run compliance testing test case 4.2.2.6 dp_panel_handle_sink_request() won't have a valid edid set in struct dp_panel::edid so we'll try to use the connectors real_edid_checksum and hit a NULL pointer dereference error because the connector pointer is never assigned. Changes in V2: -- populate panel connector at msm_dp_modeset_init() instead of at dp_panel_read_sink_caps() Changes in V3: -- remove unhelpful kernel crash trace commit text -- remove renaming dp_display parameter to dp Changes in V4: -- add more details to commit text Changes in v10: -- group into one series Changes in v11: -- drop drm/msm/dp: dp_link_parse_sink_count() return immediately if aux read Fixes: 7948fe12d47 ("drm/msm/dp: return correct edid checksum after corrupted edid checksum read") Signee-off-by: Kuogee Hsieh Reviewed-by: Bjorn Andersson Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/1642531648-8448-3-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_display.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index faf542ce49fa9..44d42c76c2a3f 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1482,6 +1482,7 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, struct drm_encoder *encoder) { struct msm_drm_private *priv; + struct dp_display_private *dp_priv; int ret; if (WARN_ON(!encoder) || WARN_ON(!dp_display) || WARN_ON(!dev)) @@ -1490,6 +1491,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, priv = dev->dev_private; dp_display->drm_dev = dev; + dp_priv = container_of(dp_display, struct dp_display_private, dp_display); + ret = dp_display_request_irq(dp_display); if (ret) { DRM_ERROR("request_irq failed, ret=%d\n", ret); @@ -1507,6 +1510,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, return ret; } + dp_priv->panel->connector = dp_display->connector; + priv->connectors[priv->num_connectors++] = dp_display->connector; dp_display->bridge = msm_dp_bridge_init(dp_display, dev, encoder); From 956653250b21ccd6dfbeba7fd6d5422de743a5b5 Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Tue, 18 Jan 2022 10:47:27 -0800 Subject: [PATCH 14/70] drm/msm/dp: add support of tps4 (training pattern 4) for HBR3 Some DP sinkers prefer to use tps4 instead of tps3 during training #2. This patch will use tps4 to perform link training #2 if sinker's DPCD supports it. Changes in V2: -- replace dp_catalog_ctrl_set_pattern() with dp_catalog_ctrl_set_pattern_state_bit() Changes in V3: -- change state_ctrl_bits type to u32 and pattern type to u8 Changes in V4: -- align } else if { and } else { Changes in v10: -- group into one series Changes in v11: -- drop drm/msm/dp: dp_link_parse_sink_count() return immediately if aux read Signed-off-by: Kuogee Hsieh Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/1642531648-8448-4-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_catalog.c | 12 ++++++------ drivers/gpu/drm/msm/dp/dp_catalog.h | 2 +- drivers/gpu/drm/msm/dp/dp_ctrl.c | 17 ++++++++++++----- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 6ae9b29044b6f..64f0b2663343b 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -456,19 +456,19 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, dp_write_p0(catalog, MMSS_DP_DSC_DTO, 0x0); } -int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, - u32 pattern) +int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, + u32 state_bit) { int bit, ret; u32 data; struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); - bit = BIT(pattern - 1); - DRM_DEBUG_DP("hw: bit=%d train=%d\n", bit, pattern); + bit = BIT(state_bit - 1); + DRM_DEBUG_DP("hw: bit=%d train=%d\n", bit, state_bit); dp_catalog_ctrl_state_ctrl(dp_catalog, bit); - bit = BIT(pattern - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT; + bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT; /* Poll for mainlink ready status */ ret = readx_poll_timeout(readl, catalog->io->dp_controller.link.base + @@ -476,7 +476,7 @@ int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, data, data & bit, POLLING_SLEEP_US, POLLING_TIMEOUT_US); if (ret < 0) { - DRM_ERROR("set pattern for link_train=%d failed\n", pattern); + DRM_ERROR("set state_bit for link_train=%d failed\n", state_bit); return ret; } return 0; diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index 6965afa81aad2..7dea1012ae66a 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -94,7 +94,7 @@ void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool enable); void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb); void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate, u32 stream_rate_khz, bool fixed_nvid); -int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, u32 pattern); +int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, u32 pattern); void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog); bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool enable); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 9c80b493f974a..f98df9355b88d 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1083,7 +1083,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl, *training_step = DP_TRAINING_1; - ret = dp_catalog_ctrl_set_pattern(ctrl->catalog, DP_TRAINING_PATTERN_1); + ret = dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, 1); if (ret) return ret; dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 | @@ -1181,7 +1181,8 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl, int *training_step) { int tries = 0, ret = 0; - char pattern; + u8 pattern; + u32 state_ctrl_bit; int const maximum_retries = 5; u8 link_status[DP_LINK_STATUS_SIZE]; @@ -1189,12 +1190,18 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl, *training_step = DP_TRAINING_2; - if (drm_dp_tps3_supported(ctrl->panel->dpcd)) + if (drm_dp_tps4_supported(ctrl->panel->dpcd)) { + pattern = DP_TRAINING_PATTERN_4; + state_ctrl_bit = 4; + } else if (drm_dp_tps3_supported(ctrl->panel->dpcd)) { pattern = DP_TRAINING_PATTERN_3; - else + state_ctrl_bit = 3; + } else { pattern = DP_TRAINING_PATTERN_2; + state_ctrl_bit = 2; + } - ret = dp_catalog_ctrl_set_pattern(ctrl->catalog, pattern); + ret = dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, state_ctrl_bit); if (ret) return ret; From 9051d629dbf7a998a40f7eac65a9512b01bc3bb8 Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Tue, 18 Jan 2022 10:47:28 -0800 Subject: [PATCH 15/70] drm/msm/dp: stop link training after link training 2 failed Each DP link training contains link training 1 followed by link training 2. There is maximum of 5 retries of DP link training before declared link training failed. It is required to stop link training at end of link training 2 if it is failed so that next link training 1 can start freshly. This patch fixes link compliance test case 4.3.1.13 (Source Device Link Training EQ Fallback Test). Changes in v10: -- group into one series Changes in v11: -- drop drm/msm/dp: dp_link_parse_sink_count() return immediately if aux read Fixes: 2e0adc765d88 ("drm/msm/dp: do not end dp link training until video is ready") Signed-off-by: Kuogee Hsieh Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/1642531648-8448-5-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index f98df9355b88d..245e1b90a956f 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1755,6 +1755,9 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl) /* end with failure */ break; /* lane == 1 already */ } + + /* stop link training before start re training */ + dp_ctrl_clear_training_pattern(ctrl); } } From d4aca422539c441a7f3fec749287b36de37d9b6b Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Mon, 24 Jan 2022 15:17:54 -0800 Subject: [PATCH 16/70] drm/msm/dp: always add fail-safe mode into connector mode list Some of DP link compliant test expects to return fail-safe mode if prefer detailed timing mode can not be supported by mainlink's lane and rate after link training. Therefore add fail-safe mode into connector mode list as backup mode. This patch fixes test case 4.2.2.1. Changes in v2: -- add Fixes text string Fixes: 4b85d405cfe9 ( "drm/msm/dp: reduce link rate if failed at link training 1") Signed-off-by: Kuogee Hsieh Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/1643066274-25814-1-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_panel.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 71db10c0f262d..f1418722c5492 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -212,6 +212,11 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel, if (drm_add_modes_noedid(connector, 640, 480)) drm_set_preferred_mode(connector, 640, 480); mutex_unlock(&connector->dev->mode_config.mutex); + } else { + /* always add fail-safe mode as backup mode */ + mutex_lock(&connector->dev->mode_config.mutex); + drm_add_modes_noedid(connector, 640, 480); + mutex_unlock(&connector->dev->mode_config.mutex); } if (panel->aux_cfg_update_done) { From 78fc35c5d9a6f633b9f458c2acb23869a4a83e50 Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Wed, 2 Feb 2022 10:56:37 -0800 Subject: [PATCH 17/70] drm/msm/dp: add connector type to enhance debug messages DP driver is a generic driver which supports both eDP and DP. For debugging purpose it is required to have capabilities to differentiate message are generated from eDP or DP. This patch add connector type into debug messages for this purpose. Changes in v3: -- replace original patch into 3 patches Signed-off-by: Kuogee Hsieh Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/1643828199-8564-2-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_display.c | 71 ++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 44d42c76c2a3f..536445bb7d452 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -394,8 +394,9 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) static void dp_display_host_phy_init(struct dp_display_private *dp) { - DRM_DEBUG_DP("core_init=%d phy_init=%d\n", - dp->core_initialized, dp->phy_initialized); + DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n", + dp->dp_display.connector_type, dp->core_initialized, + dp->phy_initialized); if (!dp->phy_initialized) { dp_ctrl_phy_init(dp->ctrl); @@ -405,8 +406,9 @@ static void dp_display_host_phy_init(struct dp_display_private *dp) static void dp_display_host_phy_exit(struct dp_display_private *dp) { - DRM_DEBUG_DP("core_init=%d phy_init=%d\n", - dp->core_initialized, dp->phy_initialized); + DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n", + dp->dp_display.connector_type, dp->core_initialized, + dp->phy_initialized); if (dp->phy_initialized) { dp_ctrl_phy_exit(dp->ctrl); @@ -416,7 +418,9 @@ static void dp_display_host_phy_exit(struct dp_display_private *dp) static void dp_display_host_init(struct dp_display_private *dp) { - DRM_DEBUG_DP("core_initialized=%d\n", dp->core_initialized); + DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n", + dp->dp_display.connector_type, dp->core_initialized, + dp->phy_initialized); dp_power_init(dp->power, false); dp_ctrl_reset_irq_ctrl(dp->ctrl, true); @@ -426,7 +430,9 @@ static void dp_display_host_init(struct dp_display_private *dp) static void dp_display_host_deinit(struct dp_display_private *dp) { - DRM_DEBUG_DP("core_initialized=%d\n", dp->core_initialized); + DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n", + dp->dp_display.connector_type, dp->core_initialized, + dp->phy_initialized); dp_ctrl_reset_irq_ctrl(dp->ctrl, false); dp_aux_deinit(dp->aux); @@ -536,7 +542,9 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) mutex_lock(&dp->event_mutex); state = dp->hpd_state; - DRM_DEBUG_DP("hpd_state=%d\n", state); + DRM_DEBUG_DP("Before, type=%d hpd_state=%d\n", + dp->dp_display.connector_type, state); + if (state == ST_DISPLAY_OFF || state == ST_SUSPENDED) { mutex_unlock(&dp->event_mutex); return 0; @@ -568,6 +576,8 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) dp_catalog_hpd_config_intr(dp->catalog, DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, true); + DRM_DEBUG_DP("After, type=%d hpd_state=%d\n", + dp->dp_display.connector_type, state); mutex_unlock(&dp->event_mutex); /* uevent will complete connection part */ @@ -584,8 +594,10 @@ static int dp_connect_pending_timeout(struct dp_display_private *dp, u32 data) mutex_lock(&dp->event_mutex); state = dp->hpd_state; - if (state == ST_CONNECT_PENDING) + if (state == ST_CONNECT_PENDING) { dp->hpd_state = ST_CONNECTED; + DRM_DEBUG_DP("type=%d\n", dp->dp_display.connector_type); + } mutex_unlock(&dp->event_mutex); @@ -618,6 +630,9 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) state = dp->hpd_state; + DRM_DEBUG_DP("Before, type=%d hpd_state=%d\n", + dp->dp_display.connector_type, state); + /* disable irq_hpd/replug interrupts */ dp_catalog_hpd_config_intr(dp->catalog, DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, false); @@ -660,13 +675,15 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) /* start sentinel checking in case of missing uevent */ dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND); - DRM_DEBUG_DP("hpd_state=%d\n", state); /* signal the disconnect event early to ensure proper teardown */ dp_display_handle_plugged_change(&dp->dp_display, false); /* enable HDP plug interrupt to prepare for next plugin */ dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, true); + DRM_DEBUG_DP("After, type=%d hpd_state=%d\n", + dp->dp_display.connector_type, state); + /* uevent will complete disconnection part */ mutex_unlock(&dp->event_mutex); return 0; @@ -679,8 +696,10 @@ static int dp_disconnect_pending_timeout(struct dp_display_private *dp, u32 data mutex_lock(&dp->event_mutex); state = dp->hpd_state; - if (state == ST_DISCONNECT_PENDING) + if (state == ST_DISCONNECT_PENDING) { dp->hpd_state = ST_DISCONNECTED; + DRM_DEBUG_DP("type=%d\n", dp->dp_display.connector_type); + } mutex_unlock(&dp->event_mutex); @@ -695,6 +714,9 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) /* irq_hpd can happen at either connected or disconnected state */ state = dp->hpd_state; + DRM_DEBUG_DP("Before, type=%d hpd_state=%d\n", + dp->dp_display.connector_type, state); + if (state == ST_DISPLAY_OFF || state == ST_SUSPENDED) { mutex_unlock(&dp->event_mutex); return 0; @@ -716,7 +738,8 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) dp_display_usbpd_attention_cb(&dp->pdev->dev); - DRM_DEBUG_DP("hpd_state=%d\n", state); + DRM_DEBUG_DP("After, type=%d hpd_state=%d\n", + dp->dp_display.connector_type, state); mutex_unlock(&dp->event_mutex); @@ -1166,8 +1189,9 @@ static irqreturn_t dp_display_irq_handler(int irq, void *dev_id) hpd_isr_status = dp_catalog_hpd_get_intr_status(dp->catalog); - DRM_DEBUG_DP("hpd isr status=%#x\n", hpd_isr_status); if (hpd_isr_status & 0x0F) { + DRM_DEBUG_DP("type=%d isr=0x%x\n", + dp->dp_display.connector_type, hpd_isr_status); /* hpd related interrupts */ if (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK) dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0); @@ -1320,8 +1344,9 @@ static int dp_pm_resume(struct device *dev) mutex_lock(&dp->event_mutex); - DRM_DEBUG_DP("Before, core_inited=%d power_on=%d\n", - dp->core_initialized, dp_display->power_on); + DRM_DEBUG_DP("Before, type=%d core_inited=%d phy_inited=%d power_on=%d\n", + dp->dp_display.connector_type, dp->core_initialized, + dp->phy_initialized, dp_display->power_on); /* start from disconnected state */ dp->hpd_state = ST_DISCONNECTED; @@ -1360,9 +1385,11 @@ static int dp_pm_resume(struct device *dev) dp_display_handle_plugged_change(dp_display, false); } - DRM_DEBUG_DP("After, sink_count=%d is_connected=%d core_inited=%d power_on=%d\n", - dp->link->sink_count, dp->dp_display.is_connected, - dp->core_initialized, dp_display->power_on); + DRM_DEBUG_DP("After, type=%d sink_count=%d is_connected=%d \ + core_inited=%d phy_inited=%d power_on=%d\n", + dp->dp_display.connector_type, dp->link->sink_count, + dp->dp_display.is_connected, dp->core_initialized, + dp->phy_initialized, dp_display->power_on); mutex_unlock(&dp->event_mutex); @@ -1379,8 +1406,9 @@ static int dp_pm_suspend(struct device *dev) mutex_lock(&dp->event_mutex); - DRM_DEBUG_DP("Before, core_inited=%d power_on=%d\n", - dp->core_initialized, dp_display->power_on); + DRM_DEBUG_DP("Before, type=%d core_inited=%d phy_inited=%d power_on=%d\n", + dp->dp_display.connector_type, dp->core_initialized, + dp->phy_initialized, dp_display->power_on); /* mainlink enabled */ if (dp_power_clk_status(dp->power, DP_CTRL_PM)) @@ -1393,8 +1421,9 @@ static int dp_pm_suspend(struct device *dev) dp->hpd_state = ST_SUSPENDED; - DRM_DEBUG_DP("After, core_inited=%d power_on=%d\n", - dp->core_initialized, dp_display->power_on); + DRM_DEBUG_DP("After, type=%d core_inited=%d phy_inited=%d power_on=%d\n", + dp->dp_display.connector_type, dp->core_initialized, + dp->phy_initialized, dp_display->power_on); mutex_unlock(&dp->event_mutex); From 2af0fc926096255a4c5a468508e8db844c77499e Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Wed, 2 Feb 2022 10:56:38 -0800 Subject: [PATCH 18/70] drm/msm/dp: enhance debug info related to dp phy DP phy should be initialized and exited symmetrically to avoid clock being stucked at either on or off error. Add debug info to cover all DP phy to identify clock issues easily. Signed-off-by: Kuogee Hsieh Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/1643828199-8564-3-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 245e1b90a956f..dcd01262910bf 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1396,6 +1396,8 @@ void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl) dp_catalog_ctrl_phy_reset(ctrl->catalog); phy_init(phy); + DRM_DEBUG_DP("phy=%p init=%d power_on=%d\n", + phy, phy->init_count, phy->power_count); } void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl) @@ -1410,6 +1412,8 @@ void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl) dp_catalog_ctrl_phy_reset(ctrl->catalog); phy_exit(phy); + DRM_DEBUG_DP("phy=%p init=%d power_on=%d\n", + phy, phy->init_count, phy->power_count); } static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl) @@ -1484,6 +1488,8 @@ static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl) phy_exit(phy); phy_init(phy); + DRM_DEBUG_DP("phy=%p init=%d power_on=%d\n", + phy, phy->init_count, phy->power_count); return 0; } @@ -1895,14 +1901,12 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) phy_power_off(phy); - DRM_DEBUG_DP("After, phy=%x init_count=%d power_on=%d\n", - (u32)(uintptr_t)phy, phy->init_count, phy->power_count); - /* aux channel down, reinit phy */ phy_exit(phy); phy_init(phy); - DRM_DEBUG_DP("DP off link/stream done\n"); + DRM_DEBUG_DP("phy=%p init=%d power_on=%d\n", + phy, phy->init_count, phy->power_count); return ret; } @@ -1933,13 +1937,9 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl) DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); } - DRM_DEBUG_DP("Before, phy=%x init_count=%d power_on=%d\n", - (u32)(uintptr_t)phy, phy->init_count, phy->power_count); - phy_power_off(phy); - - DRM_DEBUG_DP("After, phy=%x init_count=%d power_on=%d\n", - (u32)(uintptr_t)phy, phy->init_count, phy->power_count); + DRM_DEBUG_DP("phy=%p init=%d power_on=%d\n", + phy, phy->init_count, phy->power_count); return ret; } From 3a3ee71bd8e14c5e852c71f317eebfda8f88dff0 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Sat, 11 Sep 2021 15:19:20 +0200 Subject: [PATCH 19/70] drm/msm/dsi: Use "ref" fw clock instead of global name for VCO parent All DSI PHY/PLL drivers were referencing their VCO parent clock by a global name, most of which don't exist or have been renamed. These clock drivers seem to function fine without that except the 14nm driver for sdm6xx [1]. At the same time all DTs provide a "ref" clock as per the requirements of dsi-phy-common.yaml, but the clock is never used. This patchset puts that clock to use without relying on a global clock name, so that all dependencies are explicitly defined in DT (the firmware) in the end. Note that this patch intentionally breaks older firmware (DT) that relies on the clock to be found globally instead. The only affected platform is msm8974 [2] for whose dsi_phy_28nm a .name="xo" fallback is left in place to accommodate a more graceful transition period. All other platforms had the "ref" clock added to their phy node since its inception, or in a followup patch some time after. These patches wrongly assumed that the "ref" clock was actively used and have hence been listed as "Fixes:" below. Furthermore apq8064 was providing the wrong 19.2MHz cxo instead of 27MHz pxo clock, which has been addressed in [3]. It is expected that both [2] and [3] are applied to the tree well in advance of this patch such that any actual breakage is extremely unlikely, but might still occur if kernel upgrades are performed without the DT to match. After some time the fallback for msm8974 can be removed again as well. [1]: https://lore.kernel.org/linux-arm-msm/386db1a6-a1cd-3c7d-a88e-dc83f8a1be96@somainline.org/ [2]: https://lore.kernel.org/linux-arm-msm/20210830175739.143401-1-marijn.suijten@somainline.org/ [3]: https://lore.kernel.org/linux-arm-msm/20210829203027.276143-2-marijn.suijten@somainline.org/ Fixes: 79e51645a1dd ("arm64: dts: qcom: msm8916: Set 'xo_board' as ref clock of the DSI PHY") Fixes: 6969d1d9c615 ("ARM: dts: qcom-apq8064: Set 'cxo_board' as ref clock of the DSI PHY") Fixes: 0c0e72705a33 ("arm64: dts: sdm845: Set 'bi_tcxo' as ref clock of the DSI PHYs") Signed-off-by: Marijn Suijten Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20210911131922.387964-2-marijn.suijten@somainline.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c | 4 +++- drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 4 +++- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 4 +++- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 4 +++- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 4 +++- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c index d8128f50b0dd5..0b782cc18b3f4 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c @@ -562,7 +562,9 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov char clk_name[32], parent[32], vco_name[32]; char parent2[32], parent3[32], parent4[32]; struct clk_init_data vco_init = { - .parent_names = (const char *[]){ "xo" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "ref", + }, .num_parents = 1, .name = vco_name, .flags = CLK_IGNORE_UNUSED, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index 7414966f198e3..75557ac99adf1 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -802,7 +802,9 @@ static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm, struct clk_hw **prov { char clk_name[32], parent[32], vco_name[32]; struct clk_init_data vco_init = { - .parent_names = (const char *[]){ "xo" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "ref", + }, .num_parents = 1, .name = vco_name, .flags = CLK_IGNORE_UNUSED, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c index 2da673a2add69..48eab80b548e1 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c @@ -521,7 +521,9 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov { char clk_name[32], parent1[32], parent2[32], vco_name[32]; struct clk_init_data vco_init = { - .parent_names = (const char *[]){ "xo" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "ref", .name = "xo", + }, .num_parents = 1, .name = vco_name, .flags = CLK_IGNORE_UNUSED, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c index 71ed4aa0dc67e..fc56cdcc9ad64 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c @@ -385,7 +385,9 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov { char *clk_name, *parent_name, *vco_name; struct clk_init_data vco_init = { - .parent_names = (const char *[]){ "pxo" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "ref", + }, .num_parents = 1, .flags = CLK_IGNORE_UNUSED, .ops = &clk_ops_dsi_pll_28nm_vco, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index 079613d2aaa98..36eb6109cb883 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -588,7 +588,9 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide char clk_name[32], parent[32], vco_name[32]; char parent2[32], parent3[32], parent4[32]; struct clk_init_data vco_init = { - .parent_names = (const char *[]){ "bi_tcxo" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "ref", + }, .num_parents = 1, .name = vco_name, .flags = CLK_IGNORE_UNUSED, From 3bcf3d8341080a7f79d8566aeadbd3c911391cfe Mon Sep 17 00:00:00 2001 From: Rajeev Nandan Date: Mon, 31 Jan 2022 01:45:17 +0530 Subject: [PATCH 20/70] dt-bindings: msm/dsi: Add 10nm dsi phy tuning properties In most cases, the default values of DSI PHY tuning registers should be sufficient as they are fully optimized. However, in some cases where extreme board parasitics cause the eye shape to degrade, the override bits can be used to improve the signal quality. The general guidelines for DSI PHY tuning include: - High and moderate data rates may benefit from the drive strength and drive level tuning. - Drive strength tuning will affect the output impedance and may be used for matching optimization. - Drive level tuning will affect the output levels without affecting the impedance. The clock and data lanes have a calibration circuitry feature. The drive strength tuning can be done by adjusting rescode offset for hstop/hsbot, and the drive level tuning can be done by adjusting the LDO output level for the HSTX drive. Signed-off-by: Rajeev Nandan Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1643573719-32095-2-git-send-email-quic_rajeevny@quicinc.com Signed-off-by: Dmitry Baryshkov --- .../bindings/display/msm/dsi-phy-10nm.yaml | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml index 4399715953e1a..2d5a766d028f1 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml @@ -35,6 +35,38 @@ properties: Connected to DSI0_MIPI_DSI_PLL_VDDA0P9 pin for sc7180 target and connected to VDDA_MIPI_DSI_0_PLL_0P9 pin for sdm845 target + qcom,phy-rescode-offset-top: + $ref: /schemas/types.yaml#/definitions/int8-array + minItems: 5 + maxItems: 5 + description: + Integer array of offset for pull-up legs rescode for all five lanes. + To offset the drive strength from the calibrated value in an increasing + manner, -32 is the weakest and +31 is the strongest. + items: + minimum: -32 + maximum: 31 + + qcom,phy-rescode-offset-bot: + $ref: /schemas/types.yaml#/definitions/int8-array + minItems: 5 + maxItems: 5 + description: + Integer array of offset for pull-down legs rescode for all five lanes. + To offset the drive strength from the calibrated value in a decreasing + manner, -32 is the weakest and +31 is the strongest. + items: + minimum: -32 + maximum: 31 + + qcom,phy-drive-ldo-level: + $ref: "/schemas/types.yaml#/definitions/uint32" + description: + The PHY LDO has an amplitude tuning feature to adjust the LDO output + for the HSTX drive. Use supported levels (mV) to offset the drive level + from the default value. + enum: [ 375, 400, 425, 450, 475, 500 ] + required: - compatible - reg @@ -64,5 +96,9 @@ examples: clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, <&rpmhcc RPMH_CXO_CLK>; clock-names = "iface", "ref"; + + qcom,phy-rescode-offset-top = /bits/ 8 <0 0 0 0 0>; + qcom,phy-rescode-offset-bot = /bits/ 8 <0 0 0 0 0>; + qcom,phy-drive-ldo-level = <400>; }; ... From 0874cf8614c0ac0a3aa6f9420b39a5669fc2724e Mon Sep 17 00:00:00 2001 From: Rajeev Nandan Date: Mon, 31 Jan 2022 01:45:18 +0530 Subject: [PATCH 21/70] drm/msm/dsi: Add dsi phy tuning configuration support Add support for MSM DSI PHY tuning configuration. Current design is to support drive strength and drive level/amplitude tuning for 10nm PHY version, but this can be extended to other PHY versions. Signed-off-by: Rajeev Nandan Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/1643573719-32095-3-git-send-email-quic_rajeevny@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 6 ++++++ drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 2027b38617ab2..31f3490a3bcfa 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -741,6 +741,12 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) } } + if (phy->cfg->ops.parse_dt_properties) { + ret = phy->cfg->ops.parse_dt_properties(phy); + if (ret) + goto fail; + } + ret = dsi_phy_regulator_init(phy); if (ret) goto fail; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h index 4c8257581bfc2..dc91b43d5a385 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h @@ -25,6 +25,7 @@ struct msm_dsi_phy_ops { void (*save_pll_state)(struct msm_dsi_phy *phy); int (*restore_pll_state)(struct msm_dsi_phy *phy); bool (*set_continuous_clock)(struct msm_dsi_phy *phy, bool enable); + int (*parse_dt_properties)(struct msm_dsi_phy *phy); }; struct msm_dsi_phy_cfg { @@ -82,6 +83,8 @@ struct msm_dsi_dphy_timing { #define DSI_PIXEL_PLL_CLK 1 #define NUM_PROVIDED_CLKS 2 +#define DSI_LANE_MAX 5 + struct msm_dsi_phy { struct platform_device *pdev; void __iomem *base; @@ -99,6 +102,7 @@ struct msm_dsi_phy { struct msm_dsi_dphy_timing timing; const struct msm_dsi_phy_cfg *cfg; + void *tuning_cfg; enum msm_dsi_phy_usecase usecase; bool regulator_ldo_mode; From 2b0961af36f98434a2ecc1f77c474fc212a01eb0 Mon Sep 17 00:00:00 2001 From: Rajeev Nandan Date: Mon, 31 Jan 2022 01:45:19 +0530 Subject: [PATCH 22/70] drm/msm/dsi: Add 10nm dsi phy tuning configuration support The clock and data lanes of the DSI PHY have a calibration circuitry feature. As per the MSM DSI PHY tuning guidelines, the drive strength tuning can be done by adjusting rescode offset for hstop/hsbot, and the drive level tuning can be done by adjusting the LDO output level for the HSTX drive. Signed-off-by: Rajeev Nandan Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/1643573719-32095-4-git-send-email-quic_rajeevny@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c | 118 +++++++++++++++++++-- 1 file changed, 112 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c index 0b782cc18b3f4..08b015ea1b1ec 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c @@ -83,6 +83,18 @@ struct dsi_pll_10nm { #define to_pll_10nm(x) container_of(x, struct dsi_pll_10nm, clk_hw) +/** + * struct dsi_phy_10nm_tuning_cfg - Holds 10nm PHY tuning config parameters. + * @rescode_offset_top: Offset for pull-up legs rescode. + * @rescode_offset_bot: Offset for pull-down legs rescode. + * @vreg_ctrl: vreg ctrl to drive LDO level + */ +struct dsi_phy_10nm_tuning_cfg { + u8 rescode_offset_top[DSI_LANE_MAX]; + u8 rescode_offset_bot[DSI_LANE_MAX]; + u8 vreg_ctrl; +}; + /* * Global list of private DSI PLL struct pointers. We need this for bonded DSI * mode, where the master PLL's clk_ops needs access the slave's private data @@ -749,6 +761,7 @@ static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy) int i; u8 tx_dctrl[] = { 0x00, 0x00, 0x00, 0x04, 0x01 }; void __iomem *lane_base = phy->lane_base; + struct dsi_phy_10nm_tuning_cfg *tuning_cfg = phy->tuning_cfg; if (phy->cfg->quirks & DSI_PHY_10NM_QUIRK_OLD_TIMINGS) tx_dctrl[3] = 0x02; @@ -777,10 +790,13 @@ static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy) dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG2(i), 0x0); dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG3(i), i == 4 ? 0x80 : 0x0); - dsi_phy_write(lane_base + - REG_DSI_10nm_PHY_LN_OFFSET_TOP_CTRL(i), 0x0); - dsi_phy_write(lane_base + - REG_DSI_10nm_PHY_LN_OFFSET_BOT_CTRL(i), 0x0); + + /* platform specific dsi phy drive strength adjustment */ + dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_OFFSET_TOP_CTRL(i), + tuning_cfg->rescode_offset_top[i]); + dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_OFFSET_BOT_CTRL(i), + tuning_cfg->rescode_offset_bot[i]); + dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(i), tx_dctrl[i]); } @@ -801,6 +817,7 @@ static int dsi_10nm_phy_enable(struct msm_dsi_phy *phy, u32 const timeout_us = 1000; struct msm_dsi_dphy_timing *timing = &phy->timing; void __iomem *base = phy->base; + struct dsi_phy_10nm_tuning_cfg *tuning_cfg = phy->tuning_cfg; u32 data; DBG(""); @@ -836,8 +853,9 @@ static int dsi_10nm_phy_enable(struct msm_dsi_phy *phy, /* Select MS1 byte-clk */ dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_GLBL_CTRL, 0x10); - /* Enable LDO */ - dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_VREG_CTRL, 0x59); + /* Enable LDO with platform specific drive level/amplitude adjustment */ + dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_VREG_CTRL, + tuning_cfg->vreg_ctrl); /* Configure PHY lane swap (TODO: we need to calculate this) */ dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_LANE_CFG0, 0x21); @@ -924,6 +942,92 @@ static void dsi_10nm_phy_disable(struct msm_dsi_phy *phy) DBG("DSI%d PHY disabled", phy->id); } +static int dsi_10nm_phy_parse_dt(struct msm_dsi_phy *phy) +{ + struct device *dev = &phy->pdev->dev; + struct dsi_phy_10nm_tuning_cfg *tuning_cfg; + s8 offset_top[DSI_LANE_MAX] = { 0 }; /* No offset */ + s8 offset_bot[DSI_LANE_MAX] = { 0 }; /* No offset */ + u32 ldo_level = 400; /* 400mV */ + u8 level; + int ret, i; + + tuning_cfg = devm_kzalloc(dev, sizeof(*tuning_cfg), GFP_KERNEL); + if (!tuning_cfg) + return -ENOMEM; + + /* Drive strength adjustment parameters */ + ret = of_property_read_u8_array(dev->of_node, "qcom,phy-rescode-offset-top", + offset_top, DSI_LANE_MAX); + if (ret && ret != -EINVAL) { + DRM_DEV_ERROR(dev, "failed to parse qcom,phy-rescode-offset-top, %d\n", ret); + return ret; + } + + for (i = 0; i < DSI_LANE_MAX; i++) { + if (offset_top[i] < -32 || offset_top[i] > 31) { + DRM_DEV_ERROR(dev, + "qcom,phy-rescode-offset-top value %d is not in range [-32..31]\n", + offset_top[i]); + return -EINVAL; + } + tuning_cfg->rescode_offset_top[i] = 0x3f & offset_top[i]; + } + + ret = of_property_read_u8_array(dev->of_node, "qcom,phy-rescode-offset-bot", + offset_bot, DSI_LANE_MAX); + if (ret && ret != -EINVAL) { + DRM_DEV_ERROR(dev, "failed to parse qcom,phy-rescode-offset-bot, %d\n", ret); + return ret; + } + + for (i = 0; i < DSI_LANE_MAX; i++) { + if (offset_bot[i] < -32 || offset_bot[i] > 31) { + DRM_DEV_ERROR(dev, + "qcom,phy-rescode-offset-bot value %d is not in range [-32..31]\n", + offset_bot[i]); + return -EINVAL; + } + tuning_cfg->rescode_offset_bot[i] = 0x3f & offset_bot[i]; + } + + /* Drive level/amplitude adjustment parameters */ + ret = of_property_read_u32(dev->of_node, "qcom,phy-drive-ldo-level", &ldo_level); + if (ret && ret != -EINVAL) { + DRM_DEV_ERROR(dev, "failed to parse qcom,phy-drive-ldo-level, %d\n", ret); + return ret; + } + + switch (ldo_level) { + case 375: + level = 0; + break; + case 400: + level = 1; + break; + case 425: + level = 2; + break; + case 450: + level = 3; + break; + case 475: + level = 4; + break; + case 500: + level = 5; + break; + default: + DRM_DEV_ERROR(dev, "qcom,phy-drive-ldo-level %d is not supported\n", ldo_level); + return -EINVAL; + } + tuning_cfg->vreg_ctrl = 0x58 | (0x7 & level); + + phy->tuning_cfg = tuning_cfg; + + return 0; +} + const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs = { .has_phy_lane = true, .reg_cfg = { @@ -938,6 +1042,7 @@ const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs = { .pll_init = dsi_pll_10nm_init, .save_pll_state = dsi_10nm_pll_save_state, .restore_pll_state = dsi_10nm_pll_restore_state, + .parse_dt_properties = dsi_10nm_phy_parse_dt, }, .min_pll_rate = 1000000000UL, .max_pll_rate = 3500000000UL, @@ -959,6 +1064,7 @@ const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs = { .pll_init = dsi_pll_10nm_init, .save_pll_state = dsi_10nm_pll_save_state, .restore_pll_state = dsi_10nm_pll_restore_state, + .parse_dt_properties = dsi_10nm_phy_parse_dt, }, .min_pll_rate = 1000000000UL, .max_pll_rate = 3500000000UL, From 24b176d8827d167ac3b379317f60c0985f6e95aa Mon Sep 17 00:00:00 2001 From: Daniel Thompson Date: Tue, 1 Feb 2022 17:47:32 +0000 Subject: [PATCH 23/70] drm/msm/dsi: Remove spurious IRQF_ONESHOT flag Quoting the header comments, IRQF_ONESHOT is "Used by threaded interrupts which need to keep the irq line disabled until the threaded handler has been run.". When applied to an interrupt that doesn't request a threaded irq then IRQF_ONESHOT has a lesser known (undocumented?) side effect, which it to disable the forced threading of irqs (and for "normal" kernels it is a nop). In this case I can find no evidence that suppressing forced threading is intentional. Had it been intentional then a driver must adopt the raw_spinlock API in order to avoid deadlocks on PREEMPT_RT kernels (and avoid calling any kernel API that uses regular spinlocks). Fix this by removing the spurious additional flag. This change is required for my Snapdragon 7cx Gen2 tablet to boot-to-GUI with PREEMPT_RT enabled. Signed-off-by: Daniel Thompson Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220201174734.196718-2-daniel.thompson@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 6b3ced4aaaf5d..3a3f53f0c8ae1 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1877,7 +1877,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) /* do not autoenable, will be enabled later */ ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, + IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN, "dsi_isr", msm_host); if (ret < 0) { dev_err(&pdev->dev, "failed to request IRQ%u: %d\n", From 7d8e9a90509f1bd1d193a0c93cb8d1dbad9049fb Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 8 Dec 2021 01:29:00 +0300 Subject: [PATCH 24/70] drm/msm/dsi: move DSI host powerup to modeset time The DSI subsystem does not fully fall into the pre-enable/enable system of callbacks, since typically DSI device bridge drivers expect to be able to communicate with DSI devices at the pre-enable() callback. The reason is that for some DSI hosts enabling the video stream would prevent other drivers from sending DSI commands. For example see the panel-bridge driver, which does drm_panel_prepare() from the pre_enable() callback (which would be called before our pre_enable() callback, resulting in panel preparation failures as the link is not yet ready). Therewere several attempts to solve this issue, but currently the best approach is to power up the DSI link from the mode_set() callback, allowing next bridge/panel to use DSI transfers in the pre_enable() time. Follow this approach. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20211207222901.988484-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 43 +++++++++++++++++++-------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index f19bae475c966..53f018700abdb 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -336,13 +336,12 @@ dsi_mgr_connector_best_encoder(struct drm_connector *connector) return msm_dsi_get_encoder(msm_dsi); } -static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) +static void dsi_mgr_bridge_power_on(struct drm_bridge *bridge) { int id = dsi_mgr_bridge_get_id(bridge); struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); struct mipi_dsi_host *host = msm_dsi->host; - struct drm_panel *panel = msm_dsi->panel; struct msm_dsi_phy_shared_timings phy_shared_timings[DSI_MAX]; bool is_bonded_dsi = IS_BONDED_DSI(); int ret; @@ -383,6 +382,34 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) if (is_bonded_dsi && msm_dsi1) msm_dsi_host_enable_irq(msm_dsi1->host); + return; + +host1_on_fail: + msm_dsi_host_power_off(host); +host_on_fail: + dsi_mgr_phy_disable(id); +phy_en_fail: + return; +} + +static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) +{ + int id = dsi_mgr_bridge_get_id(bridge); + struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); + struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); + struct mipi_dsi_host *host = msm_dsi->host; + struct drm_panel *panel = msm_dsi->panel; + bool is_bonded_dsi = IS_BONDED_DSI(); + int ret; + + DBG("id=%d", id); + if (!msm_dsi_device_connected(msm_dsi)) + return; + + /* Do nothing with the host if it is slave-DSI in case of bonded DSI */ + if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id)) + return; + /* Always call panel functions once, because even for dual panels, * there is only one drm_panel instance. */ @@ -417,17 +444,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) if (panel) drm_panel_unprepare(panel); panel_prep_fail: - msm_dsi_host_disable_irq(host); - if (is_bonded_dsi && msm_dsi1) - msm_dsi_host_disable_irq(msm_dsi1->host); - if (is_bonded_dsi && msm_dsi1) - msm_dsi_host_power_off(msm_dsi1->host); -host1_on_fail: - msm_dsi_host_power_off(host); -host_on_fail: - dsi_mgr_phy_disable(id); -phy_en_fail: return; } @@ -573,6 +590,8 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge, msm_dsi_host_set_display_mode(host, adjusted_mode); if (is_bonded_dsi && other_dsi) msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode); + + dsi_mgr_bridge_power_on(bridge); } static const struct drm_connector_funcs dsi_mgr_connector_funcs = { From bb07af2ed2a47dc6c4d0681f275bb27d4f845465 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 17 Feb 2022 03:08:37 +0300 Subject: [PATCH 25/70] drm/msm/dsi/phy: fix 7nm v4.0 settings for C-PHY mode The dsi_7nm_phy_enable() disagrees with downstream for glbl_str_swi_cal_sel_ctrl and glbl_hstx_str_ctrl_0 values. Update programmed settings to match downstream driver. To remove the possibility for such errors in future drop less_than_1500_mhz assignment and specify settings explicitly. Fixes: 5ac178381d26 ("drm/msm/dsi: support CPHY mode for 7nm pll/phy") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220217000837.435340-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index 36eb6109cb883..6e506feb111fd 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -864,20 +864,26 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, /* Alter PHY configurations if data rate less than 1.5GHZ*/ less_than_1500_mhz = (clk_req->bitclk_rate <= 1500000000); - /* For C-PHY, no low power settings for lower clk rate */ - if (phy->cphy_mode) - less_than_1500_mhz = false; - if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) { vreg_ctrl_0 = less_than_1500_mhz ? 0x53 : 0x52; - glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00; - glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c; + if (phy->cphy_mode) { + glbl_rescode_top_ctrl = 0x00; + glbl_rescode_bot_ctrl = 0x3c; + } else { + glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00; + glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c; + } glbl_str_swi_cal_sel_ctrl = 0x00; glbl_hstx_str_ctrl_0 = 0x88; } else { vreg_ctrl_0 = less_than_1500_mhz ? 0x5B : 0x59; - glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00; - glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88; + if (phy->cphy_mode) { + glbl_str_swi_cal_sel_ctrl = 0x03; + glbl_hstx_str_ctrl_0 = 0x66; + } else { + glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00; + glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88; + } glbl_rescode_top_ctrl = 0x03; glbl_rescode_bot_ctrl = 0x3c; } From 088604d37e23e9ec01a501d0e3630bc4f02027a0 Mon Sep 17 00:00:00 2001 From: Daniel Thompson Date: Tue, 1 Feb 2022 17:47:33 +0000 Subject: [PATCH 26/70] drm/msm/hdmi: Remove spurious IRQF_ONESHOT flag Quoting the header comments, IRQF_ONESHOT is "Used by threaded interrupts which need to keep the irq line disabled until the threaded handler has been run.". When applied to an interrupt that doesn't request a threaded irq then IRQF_ONESHOT has a lesser known (undocumented?) side effect, which it to disable the forced threading of irqs. For "normal" kernels if there is no thread_fn then IRQF_ONESHOT is a nop. In this case disabling forced threading is not appropriate because the driver calls wake_up_all() (via msm_hdmi_i2c_irq) and also directly uses the regular spinlock API for locking (in msm_hdmi_hdcp_irq() ). Neither of these APIs can be called from no-thread interrupt handlers on PREEMPT_RT systems. Fix this by removing IRQF_ONESHOT. Signed-off-by: Daniel Thompson Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220201174734.196718-3-daniel.thompson@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 719720709e9e7..e167817b42958 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -306,7 +306,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, } ret = devm_request_irq(&pdev->dev, hdmi->irq, - msm_hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + msm_hdmi_irq, IRQF_TRIGGER_HIGH, "hdmi_isr", hdmi); if (ret < 0) { DRM_DEV_ERROR(dev->dev, "failed to request IRQ%u: %d\n", From 16b323ddf995d1943eed4a96367e6e761636192e Mon Sep 17 00:00:00 2001 From: Yury Norov Date: Thu, 10 Feb 2022 14:48:52 -0800 Subject: [PATCH 27/70] drm: replace bitmap_weight with bitmap_empty where appropriate smp_request_block() in drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally. Signed-off-by: Yury Norov Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220210224933.379149-9-yury.norov@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c index d7fa2c49e7410..56a3063545ec4 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c @@ -68,7 +68,7 @@ static int smp_request_block(struct mdp5_smp *smp, uint8_t reserved; /* we shouldn't be requesting blocks for an in-use client: */ - WARN_ON(bitmap_weight(cs, cnt) > 0); + WARN_ON(!bitmap_empty(cs, cnt)); reserved = smp->reserved[cid]; From 7ad7bea2fc788bb9201a2d55090cc7ddce4f4116 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 13 Jan 2022 16:51:09 +0200 Subject: [PATCH 28/70] drm/msm/dpu1: Add DMA2, DMA3 clock control to enum The enum dpu_clk_ctrl_type misses DPU_CLK_CTRL_DMA{2,3} even though this driver does actually handle both, if present: add the two in preparation for adding support for SoCs having them. Signed-off-by: AngeloGioacchino Del Regno Signed-off-by: Jami Kettunen Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220113145111.29984-2-jami.kettunen@somainline.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 31af04afda7d6..736f52c742fb5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -435,6 +435,8 @@ enum dpu_clk_ctrl_type { DPU_CLK_CTRL_RGB3, DPU_CLK_CTRL_DMA0, DPU_CLK_CTRL_DMA1, + DPU_CLK_CTRL_DMA2, + DPU_CLK_CTRL_DMA3, DPU_CLK_CTRL_CURSOR0, DPU_CLK_CTRL_CURSOR1, DPU_CLK_CTRL_INLINE_ROT0_SSPP, From 94391a14fc27383a60fc9499b631e5b6ccd9f075 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 13 Jan 2022 16:51:10 +0200 Subject: [PATCH 29/70] drm/msm/dpu1: Add MSM8998 to hw catalog Bringup functionality for MSM8998 in the DPU, driver which is mostly the same as SDM845 (just a few variations). Signed-off-by: AngeloGioacchino Del Regno Signed-off-by: Jami Kettunen Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220113145111.29984-3-jami.kettunen@somainline.org Signed-off-by: Dmitry Baryshkov --- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 329 +++++++++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 + drivers/gpu/drm/msm/msm_drv.c | 1 + 3 files changed, 320 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index aa75991903a67..2b662da312551 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -16,6 +16,9 @@ BIT(DPU_SSPP_CSC_10BIT) | BIT(DPU_SSPP_CDP) |\ BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_EXCL_RECT)) +#define VIG_MSM8998_MASK \ + (VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3)) + #define VIG_SDM845_MASK \ (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3)) @@ -25,6 +28,11 @@ #define VIG_SM8250_MASK \ (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3LITE)) +#define DMA_MSM8998_MASK \ + (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\ + BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\ + BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT)) + #define DMA_SDM845_MASK \ (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\ BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\ @@ -33,6 +41,9 @@ #define DMA_CURSOR_SDM845_MASK \ (DMA_SDM845_MASK | BIT(DPU_SSPP_CURSOR)) +#define DMA_CURSOR_MSM8998_MASK \ + (DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR)) + #define MIXER_SDM845_MASK \ (BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER)) @@ -49,6 +60,8 @@ #define MERGE_3D_SM8150_MASK (0) +#define DSPP_MSM8998_MASK BIT(DPU_DSPP_PCC) | BIT(DPU_DSPP_GC) + #define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC) #define INTF_SDM845_MASK (0) @@ -181,6 +194,22 @@ static const uint32_t plane_formats_yuv[] = { * DPU sub blocks config *************************************************************/ /* DPU top level caps */ +static const struct dpu_caps msm8998_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0x7, + .qseed_type = DPU_SSPP_SCALER_QSEED3, + .smart_dma_rev = DPU_SSPP_SMART_DMA_V1, + .ubwc_version = DPU_HW_UBWC_VER_10, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .max_hdeci_exp = MAX_HORZ_DECIMATION, + .max_vdeci_exp = MAX_VERT_DECIMATION, +}; + static const struct dpu_caps sdm845_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, @@ -251,6 +280,35 @@ static const struct dpu_caps sc7280_dpu_caps = { .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, }; +static const struct dpu_mdp_cfg msm8998_mdp[] = { + { + .name = "top_0", .id = MDP_TOP, + .base = 0x0, .len = 0x458, + .features = 0, + .highest_bank_bit = 0x2, + .clk_ctrls[DPU_CLK_CTRL_VIG0] = { + .reg_off = 0x2AC, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG1] = { + .reg_off = 0x2B4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG2] = { + .reg_off = 0x2BC, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG3] = { + .reg_off = 0x2C4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA0] = { + .reg_off = 0x2AC, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_DMA1] = { + .reg_off = 0x2B4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_DMA2] = { + .reg_off = 0x2C4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_DMA3] = { + .reg_off = 0x2C4, .bit_off = 12}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .reg_off = 0x3A8, .bit_off = 15}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .reg_off = 0x3B0, .bit_off = 15}, + }, +}; + static const struct dpu_mdp_cfg sdm845_mdp[] = { { .name = "top_0", .id = MDP_TOP, @@ -339,6 +397,39 @@ static const struct dpu_mdp_cfg sc7280_mdp[] = { /************************************************************* * CTL sub blocks config *************************************************************/ +static const struct dpu_ctl_cfg msm8998_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x1000, .len = 0x94, + .features = BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, + { + .name = "ctl_1", .id = CTL_1, + .base = 0x1200, .len = 0x94, + .features = 0, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, + { + .name = "ctl_2", .id = CTL_2, + .base = 0x1400, .len = 0x94, + .features = BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, + { + .name = "ctl_3", .id = CTL_3, + .base = 0x1600, .len = 0x94, + .features = 0, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, + { + .name = "ctl_4", .id = CTL_4, + .base = 0x1800, .len = 0x94, + .features = 0, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, +}; + static const struct dpu_ctl_cfg sdm845_ctl[] = { { .name = "ctl_0", .id = CTL_0, @@ -497,6 +588,15 @@ static const struct dpu_ctl_cfg sc7280_ctl[] = { .virt_num_formats = ARRAY_SIZE(plane_formats), \ } +static const struct dpu_sspp_sub_blks msm8998_vig_sblk_0 = + _VIG_SBLK("0", 0, DPU_SSPP_SCALER_QSEED3); +static const struct dpu_sspp_sub_blks msm8998_vig_sblk_1 = + _VIG_SBLK("1", 0, DPU_SSPP_SCALER_QSEED3); +static const struct dpu_sspp_sub_blks msm8998_vig_sblk_2 = + _VIG_SBLK("2", 0, DPU_SSPP_SCALER_QSEED3); +static const struct dpu_sspp_sub_blks msm8998_vig_sblk_3 = + _VIG_SBLK("3", 0, DPU_SSPP_SCALER_QSEED3); + static const struct dpu_sspp_sub_blks sdm845_vig_sblk_0 = _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3); static const struct dpu_sspp_sub_blks sdm845_vig_sblk_1 = @@ -523,6 +623,25 @@ static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK("11", 4); .clk_ctrl = _clkctrl \ } +static const struct dpu_sspp_cfg msm8998_sspp[] = { + SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_MSM8998_MASK, + msm8998_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), + SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_MSM8998_MASK, + msm8998_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1), + SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_MSM8998_MASK, + msm8998_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2), + SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_MSM8998_MASK, + msm8998_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3), + SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_MSM8998_MASK, + sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), + SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_MSM8998_MASK, + sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), + SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_MSM8998_MASK, + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_MSM8998_MASK, + sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +}; + static const struct dpu_sspp_cfg sdm845_sspp[] = { SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SDM845_MASK, sdm845_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), @@ -599,17 +718,6 @@ static const struct dpu_sspp_cfg sc7280_sspp[] = { * MIXER sub blocks config *************************************************************/ -/* SDM845 */ - -static const struct dpu_lm_sub_blks sdm845_lm_sblk = { - .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, - .maxblendstages = 11, /* excluding base layer */ - .blendstage_base = { /* offsets relative to mixer base */ - 0x20, 0x38, 0x50, 0x68, 0x80, 0x98, - 0xb0, 0xc8, 0xe0, 0xf8, 0x110 - }, -}; - #define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair, _dspp) \ { \ .name = _name, .id = _id, \ @@ -621,6 +729,43 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = { .dspp = _dspp \ } +/* MSM8998 */ + +static const struct dpu_lm_sub_blks msm8998_lm_sblk = { + .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .maxblendstages = 7, /* excluding base layer */ + .blendstage_base = { /* offsets relative to mixer base */ + 0x20, 0x50, 0x80, 0xb0, 0x230, + 0x260, 0x290 + }, +}; + +static const struct dpu_lm_cfg msm8998_lm[] = { + LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK, + &msm8998_lm_sblk, PINGPONG_0, LM_2, DSPP_0), + LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK, + &msm8998_lm_sblk, PINGPONG_1, LM_5, DSPP_1), + LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK, + &msm8998_lm_sblk, PINGPONG_2, LM_0, 0), + LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK, + &msm8998_lm_sblk, PINGPONG_MAX, 0, 0), + LM_BLK("lm_4", LM_4, 0x48000, MIXER_SDM845_MASK, + &msm8998_lm_sblk, PINGPONG_MAX, 0, 0), + LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK, + &msm8998_lm_sblk, PINGPONG_3, LM_1, 0), +}; + +/* SDM845 */ + +static const struct dpu_lm_sub_blks sdm845_lm_sblk = { + .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .maxblendstages = 11, /* excluding base layer */ + .blendstage_base = { /* offsets relative to mixer base */ + 0x20, 0x38, 0x50, 0x68, 0x80, 0x98, + 0xb0, 0xc8, 0xe0, 0xf8, 0x110 + }, +}; + static const struct dpu_lm_cfg sdm845_lm[] = { LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK, &sdm845_lm_sblk, PINGPONG_0, LM_1, 0), @@ -682,6 +827,13 @@ static const struct dpu_lm_cfg sc7280_lm[] = { /************************************************************* * DSPP sub blocks config *************************************************************/ +static const struct dpu_dspp_sub_blks msm8998_dspp_sblk = { + .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700, + .len = 0x90, .version = 0x10007}, + .gc = { .id = DPU_DSPP_GC, .base = 0x17c0, + .len = 0x90, .version = 0x10007}, +}; + static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = { .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700, .len = 0x90, .version = 0x10000}, @@ -700,6 +852,13 @@ static const struct dpu_dspp_sub_blks sm8150_dspp_sblk = { .sblk = _sblk \ } +static const struct dpu_dspp_cfg msm8998_dspp[] = { + DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_MSM8998_MASK, + &msm8998_dspp_sblk), + DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_MSM8998_MASK, + &msm8998_dspp_sblk), +}; + static const struct dpu_dspp_cfg sc7180_dspp[] = { DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK, &sc7180_dspp_sblk), @@ -836,6 +995,13 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = { .intr_vsync = DPU_IRQ_IDX(_reg, _vsync_bit), \ } +static const struct dpu_intf_cfg msm8998_intf[] = { + INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25), + INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27), + INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29), + INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_HDMI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31), +}; + static const struct dpu_intf_cfg sdm845_intf[] = { INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25), INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27), @@ -865,9 +1031,55 @@ static const struct dpu_intf_cfg sc7280_intf[] = { * VBIF sub blocks config *************************************************************/ /* VBIF QOS remap */ +static const u32 msm8998_rt_pri_lvl[] = {1, 2, 2, 2}; +static const u32 msm8998_nrt_pri_lvl[] = {1, 1, 1, 1}; static const u32 sdm845_rt_pri_lvl[] = {3, 3, 4, 4, 5, 5, 6, 6}; static const u32 sdm845_nrt_pri_lvl[] = {3, 3, 3, 3, 3, 3, 3, 3}; +static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = { + { + .pps = 1088 * 1920 * 30, + .ot_limit = 2, + }, + { + .pps = 1088 * 1920 * 60, + .ot_limit = 6, + }, + { + .pps = 3840 * 2160 * 30, + .ot_limit = 16, + }, +}; + +static const struct dpu_vbif_cfg msm8998_vbif[] = { + { + .name = "vbif_0", .id = VBIF_0, + .base = 0, .len = 0x1040, + .default_ot_rd_limit = 32, + .default_ot_wr_limit = 32, + .features = BIT(DPU_VBIF_QOS_REMAP) | BIT(DPU_VBIF_QOS_OTLIM), + .xin_halt_timeout = 0x4000, + .dynamic_ot_rd_tbl = { + .count = ARRAY_SIZE(msm8998_ot_rdwr_cfg), + .cfg = msm8998_ot_rdwr_cfg, + }, + .dynamic_ot_wr_tbl = { + .count = ARRAY_SIZE(msm8998_ot_rdwr_cfg), + .cfg = msm8998_ot_rdwr_cfg, + }, + .qos_rt_tbl = { + .npriority_lvl = ARRAY_SIZE(msm8998_rt_pri_lvl), + .priority_lvl = msm8998_rt_pri_lvl, + }, + .qos_nrt_tbl = { + .npriority_lvl = ARRAY_SIZE(msm8998_nrt_pri_lvl), + .priority_lvl = msm8998_nrt_pri_lvl, + }, + .memtype_count = 14, + .memtype = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, + }, +}; + static const struct dpu_vbif_cfg sdm845_vbif[] = { { .name = "vbif_0", .id = VBIF_0, @@ -908,6 +1120,22 @@ static const struct dpu_reg_dma_cfg sm8250_regdma = { *************************************************************/ /* SSPP QOS LUTs */ +static const struct dpu_qos_lut_entry msm8998_qos_linear[] = { + {.fl = 4, .lut = 0x1b}, + {.fl = 5, .lut = 0x5b}, + {.fl = 6, .lut = 0x15b}, + {.fl = 7, .lut = 0x55b}, + {.fl = 8, .lut = 0x155b}, + {.fl = 9, .lut = 0x555b}, + {.fl = 10, .lut = 0x1555b}, + {.fl = 11, .lut = 0x5555b}, + {.fl = 12, .lut = 0x15555b}, + {.fl = 13, .lut = 0x55555b}, + {.fl = 14, .lut = 0}, + {.fl = 1, .lut = 0x1b}, + {.fl = 0, .lut = 0} +}; + static const struct dpu_qos_lut_entry sdm845_qos_linear[] = { {.fl = 4, .lut = 0x357}, {.fl = 5, .lut = 0x3357}, @@ -923,6 +1151,15 @@ static const struct dpu_qos_lut_entry sdm845_qos_linear[] = { {.fl = 0, .lut = 0x11222222223357} }; +static const struct dpu_qos_lut_entry msm8998_qos_macrotile[] = { + {.fl = 10, .lut = 0x1aaff}, + {.fl = 11, .lut = 0x5aaff}, + {.fl = 12, .lut = 0x15aaff}, + {.fl = 13, .lut = 0x55aaff}, + {.fl = 1, .lut = 0x1aaff}, + {.fl = 0, .lut = 0}, +}; + static const struct dpu_qos_lut_entry sc7180_qos_linear[] = { {.fl = 0, .lut = 0x0011222222335777}, }; @@ -944,6 +1181,10 @@ static const struct dpu_qos_lut_entry sc7180_qos_macrotile[] = { {.fl = 0, .lut = 0x0011223344556677}, }; +static const struct dpu_qos_lut_entry msm8998_qos_nrt[] = { + {.fl = 0, .lut = 0x0}, +}; + static const struct dpu_qos_lut_entry sdm845_qos_nrt[] = { {.fl = 0, .lut = 0x0}, }; @@ -952,6 +1193,42 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = { {.fl = 0, .lut = 0x0}, }; +static const struct dpu_perf_cfg msm8998_perf_data = { + .max_bw_low = 6700000, + .max_bw_high = 6700000, + .min_core_ib = 2400000, + .min_llcc_ib = 800000, + .min_dram_ib = 800000, + .undersized_prefill_lines = 2, + .xtra_prefill_lines = 2, + .dest_scale_prefill_lines = 3, + .macrotile_prefill_lines = 4, + .yuv_nv12_prefill_lines = 8, + .linear_prefill_lines = 1, + .downscaling_prefill_lines = 1, + .amortizable_threshold = 25, + .min_prefill_lines = 25, + .danger_lut_tbl = {0xf, 0xffff, 0x0}, + .safe_lut_tbl = {0xfffc, 0xff00, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(msm8998_qos_linear), + .entries = msm8998_qos_linear + }, + {.nentry = ARRAY_SIZE(msm8998_qos_macrotile), + .entries = msm8998_qos_macrotile + }, + {.nentry = ARRAY_SIZE(msm8998_qos_nrt), + .entries = msm8998_qos_nrt + }, + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 200, + .bw_inefficiency_factor = 120, +}; + static const struct dpu_perf_cfg sdm845_perf_data = { .max_bw_low = 6800000, .max_bw_high = 6800000, @@ -1106,6 +1383,34 @@ static const struct dpu_perf_cfg sc7280_perf_data = { * Hardware catalog init *************************************************************/ +/* + * msm8998_cfg_init(): populate sdm845 dpu sub-blocks reg offsets + * and instance counts. + */ +static void msm8998_cfg_init(struct dpu_mdss_cfg *dpu_cfg) +{ + *dpu_cfg = (struct dpu_mdss_cfg){ + .caps = &msm8998_dpu_caps, + .mdp_count = ARRAY_SIZE(msm8998_mdp), + .mdp = msm8998_mdp, + .ctl_count = ARRAY_SIZE(msm8998_ctl), + .ctl = msm8998_ctl, + .sspp_count = ARRAY_SIZE(msm8998_sspp), + .sspp = msm8998_sspp, + .mixer_count = ARRAY_SIZE(msm8998_lm), + .mixer = msm8998_lm, + .pingpong_count = ARRAY_SIZE(sdm845_pp), + .pingpong = sdm845_pp, + .intf_count = ARRAY_SIZE(msm8998_intf), + .intf = msm8998_intf, + .vbif_count = ARRAY_SIZE(msm8998_vbif), + .vbif = msm8998_vbif, + .reg_dma_count = 0, + .perf = msm8998_perf_data, + .mdss_irqs = IRQ_SM8250_MASK, + }; +} + /* * sdm845_cfg_init(): populate sdm845 dpu sub-blocks reg offsets * and instance counts. @@ -1256,6 +1561,8 @@ static void sc7280_cfg_init(struct dpu_mdss_cfg *dpu_cfg) } static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = { + { .hw_rev = DPU_HW_VER_300, .cfg_init = msm8998_cfg_init}, + { .hw_rev = DPU_HW_VER_301, .cfg_init = msm8998_cfg_init}, { .hw_rev = DPU_HW_VER_400, .cfg_init = sdm845_cfg_init}, { .hw_rev = DPU_HW_VER_401, .cfg_init = sdm845_cfg_init}, { .hw_rev = DPU_HW_VER_500, .cfg_init = sm8150_cfg_init}, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 47fe11a84a77c..83a19bfe5f9cb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1348,6 +1348,7 @@ static const struct dev_pm_ops dpu_pm_ops = { }; const struct of_device_id dpu_dt_match[] = { + { .compatible = "qcom,msm8998-dpu", }, { .compatible = "qcom,sdm845-dpu", }, { .compatible = "qcom,sc7180-dpu", }, { .compatible = "qcom,sc7280-dpu", }, diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 555666e3f9603..e85c010bd3294 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1435,6 +1435,7 @@ static void msm_pdev_shutdown(struct platform_device *pdev) static const struct of_device_id dt_match[] = { { .compatible = "qcom,mdp4", .data = (void *)KMS_MDP4 }, { .compatible = "qcom,mdss", .data = (void *)KMS_MDP5 }, + { .compatible = "qcom,msm8998-mdss", .data = (void *)KMS_DPU }, { .compatible = "qcom,sdm845-mdss", .data = (void *)KMS_DPU }, { .compatible = "qcom,sc7180-mdss", .data = (void *)KMS_DPU }, { .compatible = "qcom,sc7280-mdss", .data = (void *)KMS_DPU }, From 6e986a8f1cf15810be49e439acbc4a1499dd64b7 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 13 Jan 2022 16:51:11 +0200 Subject: [PATCH 30/70] dt-bindings: display: msm: Add binding for msm8998 dpu Add yaml binding for msm8998 dpu1 support. Signed-off-by: AngeloGioacchino Del Regno Signed-off-by: Jami Kettunen Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20220113145111.29984-4-jami.kettunen@somainline.org Signed-off-by: Dmitry Baryshkov --- .../bindings/display/msm/dpu-msm8998.yaml | 219 ++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml diff --git a/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml b/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml new file mode 100644 index 0000000000000..167bc48748d77 --- /dev/null +++ b/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml @@ -0,0 +1,219 @@ +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/msm/dpu-msm8998.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Display DPU dt properties for MSM8998 target + +maintainers: + - AngeloGioacchino Del Regno + +description: | + Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates + sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree + bindings of MDSS and DPU are mentioned for MSM8998 target. + +properties: + compatible: + items: + - const: qcom,msm8998-mdss + + reg: + maxItems: 1 + + reg-names: + const: mdss + + power-domains: + maxItems: 1 + + clocks: + items: + - description: Display AHB clock + - description: Display AXI clock + - description: Display core clock + + clock-names: + items: + - const: iface + - const: bus + - const: core + + interrupts: + maxItems: 1 + + interrupt-controller: true + + "#address-cells": true + + "#size-cells": true + + "#interrupt-cells": + const: 1 + + iommus: + items: + - description: Phandle to apps_smmu node with SID mask for Hard-Fail port0 + + ranges: true + +patternProperties: + "^display-controller@[0-9a-f]+$": + type: object + description: Node containing the properties of DPU. + + properties: + compatible: + items: + - const: qcom,msm8998-dpu + + reg: + items: + - description: Address offset and size for mdp register set + - description: Address offset and size for regdma register set + - description: Address offset and size for vbif register set + - description: Address offset and size for non-realtime vbif register set + + reg-names: + items: + - const: mdp + - const: regdma + - const: vbif + - const: vbif_nrt + + clocks: + items: + - description: Display ahb clock + - description: Display axi clock + - description: Display mem-noc clock + - description: Display core clock + - description: Display vsync clock + + clock-names: + items: + - const: iface + - const: bus + - const: mnoc + - const: core + - const: vsync + + interrupts: + maxItems: 1 + + power-domains: + maxItems: 1 + + operating-points-v2: true + ports: + $ref: /schemas/graph.yaml#/properties/ports + description: | + Contains the list of output ports from DPU device. These ports + connect to interfaces that are external to the DPU hardware, + such as DSI, DP etc. Each output port contains an endpoint that + describes how it is connected to an external interface. + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: DPU_INTF1 (DSI1) + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: DPU_INTF2 (DSI2) + + required: + - port@0 + - port@1 + + required: + - compatible + - reg + - reg-names + - clocks + - interrupts + - power-domains + - operating-points-v2 + - ports + +required: + - compatible + - reg + - reg-names + - power-domains + - clocks + - interrupts + - interrupt-controller + - iommus + - ranges + +additionalProperties: false + +examples: + - | + #include + #include + #include + + display-subsystem@c900000 { + compatible = "qcom,msm8998-mdss"; + reg = <0x0c900000 0x1000>; + reg-names = "mdss"; + + clocks = <&mmcc MDSS_AHB_CLK>, + <&mmcc MDSS_AXI_CLK>, + <&mmcc MDSS_MDP_CLK>; + clock-names = "iface", "bus", "core"; + + #address-cells = <1>; + #interrupt-cells = <1>; + #size-cells = <1>; + + interrupts = ; + interrupt-controller; + iommus = <&mmss_smmu 0>; + + power-domains = <&mmcc MDSS_GDSC>; + ranges; + + display-controller@c901000 { + compatible = "qcom,msm8998-dpu"; + reg = <0x0c901000 0x8f000>, + <0x0c9a8e00 0xf0>, + <0x0c9b0000 0x2008>, + <0x0c9b8000 0x1040>; + reg-names = "mdp", "regdma", "vbif", "vbif_nrt"; + + clocks = <&mmcc MDSS_AHB_CLK>, + <&mmcc MDSS_AXI_CLK>, + <&mmcc MNOC_AHB_CLK>, + <&mmcc MDSS_MDP_CLK>, + <&mmcc MDSS_VSYNC_CLK>; + clock-names = "iface", "bus", "mnoc", "core", "vsync"; + + interrupt-parent = <&mdss>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmpd MSM8998_VDDMX>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + + port@1 { + reg = <1>; + dpu_intf2_out: endpoint { + remote-endpoint = <&dsi1_in>; + }; + }; + }; + }; + }; +... From 306dfc593362271d7d789a7cdea2ba6c2153dcd5 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Tue, 8 Feb 2022 09:23:21 +0800 Subject: [PATCH 31/70] drm/msm/dpu: clean up some inconsistent indenting Eliminate the follow smatch warning: drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:411 _dpu_crtc_blend_setup_mixer() warn: inconsistent indenting Reported-by: Abaci Robot Signed-off-by: Yang Li Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220208012321.43587-1-yang.lee@linux.alibaba.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index e7c9fe1a250fb..662b7bc9c219c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -408,7 +408,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, if (ctl->ops.set_active_pipes) ctl->ops.set_active_pipes(ctl, fetch_active); - _dpu_crtc_program_lm_output_roi(crtc); + _dpu_crtc_program_lm_output_roi(crtc); } /** From 061ee4575c7131661d513964206ca511295a6c07 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 10 Feb 2022 17:11:04 +0530 Subject: [PATCH 32/70] drm/msm/dpu: Remove set but unused variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get warning: In function ‘dpu_encoder_virt_enable’: drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c:1145:33: warning: variable ‘priv’ set but not used [-Wunused-but-set-variable] 1145 | struct msm_drm_private *priv; In function ‘dpu_encoder_virt_disable’: drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c:1182:33: warning: variable ‘priv’ set but not used [-Wunused-but-set-variable] 1182 | struct msm_drm_private *priv; Remove these unused but set variables Signed-off-by: Vinod Koul Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220210114106.290669-1-vkoul@kernel.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1e648db439f9b..132844801e92d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1142,14 +1142,12 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc = NULL; int ret = 0; - struct msm_drm_private *priv; struct drm_display_mode *cur_mode = NULL; dpu_enc = to_dpu_encoder_virt(drm_enc); mutex_lock(&dpu_enc->enc_lock); cur_mode = &dpu_enc->base.crtc->state->adjusted_mode; - priv = drm_enc->dev->dev_private; trace_dpu_enc_enable(DRMID(drm_enc), cur_mode->hdisplay, cur_mode->vdisplay); @@ -1179,7 +1177,6 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc = NULL; - struct msm_drm_private *priv; int i = 0; dpu_enc = to_dpu_encoder_virt(drm_enc); @@ -1188,8 +1185,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) mutex_lock(&dpu_enc->enc_lock); dpu_enc->enabled = false; - priv = drm_enc->dev->dev_private; - trace_dpu_enc_disable(DRMID(drm_enc)); /* wait for idle */ From 651988cc2bcc55166a3215c8e29c01f60b7de367 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 10 Feb 2022 17:11:05 +0530 Subject: [PATCH 33/70] drm/msm/dpu: Update the comment style The multi line comment style is wrongly used as kernel-doc comment. This gives a warning: drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c:17: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst Update the style to fix this. Signed-off-by: Vinod Koul Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220210114106.290669-2-vkoul@kernel.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index a77a5eaa78ad2..9341c88a336f9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -13,7 +13,7 @@ #include "dpu_hw_mdss.h" #include "dpu_trace.h" -/** +/* * Register offsets in MDSS register file for the interrupt registers * w.r.t. to the MDP base */ From 07567d596eb0ad0f736fce4efa98af4d7b015799 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 10 Feb 2022 17:11:06 +0530 Subject: [PATCH 34/70] drm/msm/dpu: Update function parameter documentation dpu_core_irq_callback_handler() function comments seem to have become stale and emit a warning: drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c:147: warning: Function parameter or member 'dpu_kms' not described in 'dpu_core_irq_callback_handler' drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c:147: warning: Excess function parameter 'arg' description in 'dpu_core_irq_callback_handler' Fix by updating the documentation Signed-off-by: Vinod Koul Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220210114106.290669-3-vkoul@kernel.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index 9341c88a336f9..27073fd49fee0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -140,7 +140,7 @@ static const struct dpu_intr_reg dpu_intr_set[] = { /** * dpu_core_irq_callback_handler - dispatch core interrupts - * @arg: private data of callback handler + * @dpu_kms: Pointer to DPU's KMS structure * @irq_idx: interrupt index */ static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, int irq_idx) From 03490e114aefc1655be427f7bad08b5f8aa80971 Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Mon, 14 Feb 2022 13:46:54 -0800 Subject: [PATCH 35/70] drm/msm: populate intf_audio_select() base on hardware capability intf_audio_select() callback function use to configure HDMI_DP_CORE_SELECT to decide audio output routes to HDMI or DP interface. HDMI is obsoleted at newer chipset. To keep supporting legacy hdmi application, intf_audio_select call back function have to be populated base on hardware chip capability where legacy chipsets have has_audio_select flag set to true. Changes in V2: -- remove has_audio_select flag -- add BIT(DPU_MDP_AUDIO_SELECT) into dpu_mdp_cfg Signed-off-by: Kuogee Hsieh Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/1644875214-12944-1-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 2b662da312551..d3151ac4ca881 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -313,7 +313,7 @@ static const struct dpu_mdp_cfg sdm845_mdp[] = { { .name = "top_0", .id = MDP_TOP, .base = 0x0, .len = 0x45C, - .features = 0, + .features = BIT(DPU_MDP_AUDIO_SELECT), .highest_bank_bit = 0x2, .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2AC, .bit_off = 0}, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 736f52c742fb5..c67a8e63171f2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -87,6 +87,7 @@ enum { DPU_MDP_BWC, DPU_MDP_UBWC_1_0, DPU_MDP_UBWC_1_5, + DPU_MDP_AUDIO_SELECT, DPU_MDP_MAX }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c index 282e3c6c6d48d..ab3ef162b6668 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c @@ -268,7 +268,9 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops, ops->get_danger_status = dpu_hw_get_danger_status; ops->setup_vsync_source = dpu_hw_setup_vsync_source; ops->get_safe_status = dpu_hw_get_safe_status; - ops->intf_audio_select = dpu_hw_intf_audio_select; + + if (cap & BIT(DPU_MDP_AUDIO_SELECT)) + ops->intf_audio_select = dpu_hw_intf_audio_select; } static const struct dpu_mdp_cfg *_top_offset(enum dpu_mdp mdp, From ee216bd1aa5f124003f33d5d15b979c594c2775c Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 22 Jan 2022 00:06:13 +0300 Subject: [PATCH 36/70] drm/msm/dpu: drop unused lm_max_width from RM No code uses lm_max_width from resource manager, so drop it. Instead of calculating the lm_max_width, code can use max_mixer_width field from the hw catalog. Signed-off-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220121210618.3482550-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 12 ------------ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 4 ---- 2 files changed, 16 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index f9c83d6e427ad..b5b1ea1e4de63 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -114,18 +114,6 @@ int dpu_rm_init(struct dpu_rm *rm, goto fail; } rm->mixer_blks[lm->id - LM_0] = &hw->base; - - if (!rm->lm_max_width) { - rm->lm_max_width = lm->sblk->maxwidth; - } else if (rm->lm_max_width != lm->sblk->maxwidth) { - /* - * Don't expect to have hw where lm max widths differ. - * If found, take the min. - */ - DPU_ERROR("unsupported: lm maxwidth differs\n"); - if (rm->lm_max_width > lm->sblk->maxwidth) - rm->lm_max_width = lm->sblk->maxwidth; - } } for (i = 0; i < cat->merge_3d_count; i++) { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h index 1f12c8d5b8aa0..0f27759211b5d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h @@ -20,8 +20,6 @@ struct dpu_global_state; * @ctl_blks: array of ctl hardware resources * @intf_blks: array of intf hardware resources * @dspp_blks: array of dspp hardware resources - * @lm_max_width: cached layer mixer maximum width - * @rm_lock: resource manager mutex */ struct dpu_rm { struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0]; @@ -30,8 +28,6 @@ struct dpu_rm { struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0]; struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0]; struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0]; - - uint32_t lm_max_width; }; /** From d5c5e78f217172e87d8fb2c3418dd8b58b4adfcb Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 22 Jan 2022 00:06:14 +0300 Subject: [PATCH 37/70] drm/msm/dpu: add DSPP blocks teardown Add missing calls to dpu_hw_dspp_destroy() to free resources allocated for DSPP hardware blocks. Fixes: e47616df008b ("drm/msm/dpu: add support for color processing blocks in dpu driver") Signed-off-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220121210618.3482550-3-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index b5b1ea1e4de63..63ed0d7df8487 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -35,6 +35,14 @@ int dpu_rm_destroy(struct dpu_rm *rm) { int i; + for (i = 0; i < ARRAY_SIZE(rm->dspp_blks); i++) { + struct dpu_hw_dspp *hw; + + if (rm->dspp_blks[i]) { + hw = to_dpu_hw_dspp(rm->dspp_blks[i]); + dpu_hw_dspp_destroy(hw); + } + } for (i = 0; i < ARRAY_SIZE(rm->pingpong_blks); i++) { struct dpu_hw_pingpong *hw; From ef58e0ad34365e2c8274b74e6e745b8c180ff0d3 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 22 Jan 2022 00:06:15 +0300 Subject: [PATCH 38/70] drm/msm/dpu: get INTF blocks directly rather than through RM INTF blocks are not really handled by resource manager, they are assigned at dpu_encoder_setup_display using dpu_encoder_get_intf(). Then this allocation is passed to RM and then returned to then dpu_encoder. So allocate them outside of RM and use them directly. Signed-off-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220121210618.3482550-4-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 36 +--------- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 16 ----- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 5 -- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 8 --- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 8 --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 68 ++----------------- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 8 +++ 8 files changed, 16 insertions(+), 134 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 132844801e92d..d442d4b9484fe 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -420,26 +420,6 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc) return linecount; } -void dpu_encoder_get_hw_resources(struct drm_encoder *drm_enc, - struct dpu_encoder_hw_resources *hw_res) -{ - struct dpu_encoder_virt *dpu_enc = NULL; - int i = 0; - - dpu_enc = to_dpu_encoder_virt(drm_enc); - DPU_DEBUG_ENC(dpu_enc, "\n"); - - /* Query resources used by phys encs, expected to be without overlap */ - memset(hw_res, 0, sizeof(*hw_res)); - - for (i = 0; i < dpu_enc->num_phys_encs; i++) { - struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; - - if (phys->ops.get_hw_resources) - phys->ops.get_hw_resources(phys, hw_res); - } -} - static void dpu_encoder_destroy(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc = NULL; @@ -973,7 +953,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL }; int num_lm, num_ctl, num_pp; - int i, j; + int i; if (!drm_enc) { DPU_ERROR("invalid encoder\n"); @@ -1040,8 +1020,6 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, cstate->num_mixers = num_lm; for (i = 0; i < dpu_enc->num_phys_encs; i++) { - int num_blk; - struct dpu_hw_blk *hw_blk[MAX_CHANNELS_PER_ENC]; struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; if (!dpu_enc->hw_pp[i]) { @@ -1059,16 +1037,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, phys->hw_pp = dpu_enc->hw_pp[i]; phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]); - num_blk = dpu_rm_get_assigned_resources(&dpu_kms->rm, - global_state, drm_enc->base.id, DPU_HW_BLK_INTF, - hw_blk, ARRAY_SIZE(hw_blk)); - for (j = 0; j < num_blk; j++) { - struct dpu_hw_intf *hw_intf; - - hw_intf = to_dpu_hw_intf(hw_blk[i]); - if (hw_intf->idx == phys->intf_idx) - phys->hw_intf = hw_intf; - } + if (phys->intf_idx >= INTF_0 && phys->intf_idx < INTF_MAX) + phys->hw_intf = dpu_rm_get_intf(&dpu_kms->rm, phys->intf_idx); if (!phys->hw_intf) { DPU_ERROR_ENC(dpu_enc, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index e241914a96777..722dd7db6bdf8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -18,22 +18,6 @@ #define IDLE_TIMEOUT (66 - 16/2) -/** - * Encoder functions and data types - * @intfs: Interfaces this encoder is using, INTF_MODE_NONE if unused - */ -struct dpu_encoder_hw_resources { - enum dpu_intf_mode intfs[INTF_MAX]; -}; - -/** - * dpu_encoder_get_hw_resources - Populate table of required hardware resources - * @encoder: encoder pointer - * @hw_res: resource table to populate with encoder required resources - */ -void dpu_encoder_get_hw_resources(struct drm_encoder *encoder, - struct dpu_encoder_hw_resources *hw_res); - /** * dpu_encoder_assign_crtc - Link the encoder to the crtc it's assigned to * @encoder: encoder pointer diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index e7270eb6b84be..42febfce79c73 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -91,9 +91,6 @@ struct dpu_encoder_virt_ops { * @disable: DRM Call. Disable mode. * @atomic_check: DRM Call. Atomic check new DRM state. * @destroy: DRM Call. Destroy and release resources. - * @get_hw_resources: Populate the structure with the hardware - * resources that this phys_enc is using. - * Expect no overlap between phys_encs. * @control_vblank_irq Register/Deregister for VBLANK IRQ * @wait_for_commit_done: Wait for hardware to have flushed the * current pending frames to hardware @@ -129,8 +126,6 @@ struct dpu_encoder_phys_ops { struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state); void (*destroy)(struct dpu_encoder_phys *encoder); - void (*get_hw_resources)(struct dpu_encoder_phys *encoder, - struct dpu_encoder_hw_resources *hw_res); int (*control_vblank_irq)(struct dpu_encoder_phys *enc, bool enable); int (*wait_for_commit_done)(struct dpu_encoder_phys *phys_enc); int (*wait_for_tx_complete)(struct dpu_encoder_phys *phys_enc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index 34a6940d12c59..7d2beea9cc4e8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -534,13 +534,6 @@ static void dpu_encoder_phys_cmd_destroy(struct dpu_encoder_phys *phys_enc) kfree(cmd_enc); } -static void dpu_encoder_phys_cmd_get_hw_resources( - struct dpu_encoder_phys *phys_enc, - struct dpu_encoder_hw_resources *hw_res) -{ - hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_CMD; -} - static void dpu_encoder_phys_cmd_prepare_for_kickoff( struct dpu_encoder_phys *phys_enc) { @@ -736,7 +729,6 @@ static void dpu_encoder_phys_cmd_init_ops( ops->enable = dpu_encoder_phys_cmd_enable; ops->disable = dpu_encoder_phys_cmd_disable; ops->destroy = dpu_encoder_phys_cmd_destroy; - ops->get_hw_resources = dpu_encoder_phys_cmd_get_hw_resources; ops->control_vblank_irq = dpu_encoder_phys_cmd_control_vblank_irq; ops->wait_for_commit_done = dpu_encoder_phys_cmd_wait_for_commit_done; ops->prepare_for_kickoff = dpu_encoder_phys_cmd_prepare_for_kickoff; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index ddd9d89cd456a..db6a9b896e426 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -465,13 +465,6 @@ static void dpu_encoder_phys_vid_destroy(struct dpu_encoder_phys *phys_enc) kfree(phys_enc); } -static void dpu_encoder_phys_vid_get_hw_resources( - struct dpu_encoder_phys *phys_enc, - struct dpu_encoder_hw_resources *hw_res) -{ - hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_VIDEO; -} - static int dpu_encoder_phys_vid_wait_for_vblank( struct dpu_encoder_phys *phys_enc) { @@ -680,7 +673,6 @@ static void dpu_encoder_phys_vid_init_ops(struct dpu_encoder_phys_ops *ops) ops->enable = dpu_encoder_phys_vid_enable; ops->disable = dpu_encoder_phys_vid_disable; ops->destroy = dpu_encoder_phys_vid_destroy; - ops->get_hw_resources = dpu_encoder_phys_vid_get_hw_resources; ops->control_vblank_irq = dpu_encoder_phys_vid_control_vblank_irq; ops->wait_for_commit_done = dpu_encoder_phys_vid_wait_for_commit_done; ops->wait_for_vblank = dpu_encoder_phys_vid_wait_for_vblank; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 2d385b4b7f5e8..3f518c809e333 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -144,7 +144,6 @@ struct dpu_global_state { uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0]; uint32_t mixer_to_enc_id[LM_MAX - LM_0]; uint32_t ctl_to_enc_id[CTL_MAX - CTL_0]; - uint32_t intf_to_enc_id[INTF_MAX - INTF_0]; uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0]; }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 63ed0d7df8487..8df21a46308e5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -28,7 +28,6 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx, */ struct dpu_rm_requirements { struct msm_display_topology topology; - struct dpu_encoder_hw_resources hw_res; }; int dpu_rm_destroy(struct dpu_rm *rm) @@ -448,54 +447,6 @@ static int _dpu_rm_reserve_ctls( return 0; } -static int _dpu_rm_reserve_intf( - struct dpu_rm *rm, - struct dpu_global_state *global_state, - uint32_t enc_id, - uint32_t id) -{ - int idx = id - INTF_0; - - if (idx < 0 || idx >= ARRAY_SIZE(rm->intf_blks)) { - DPU_ERROR("invalid intf id: %d", id); - return -EINVAL; - } - - if (!rm->intf_blks[idx]) { - DPU_ERROR("couldn't find intf id %d\n", id); - return -EINVAL; - } - - if (reserved_by_other(global_state->intf_to_enc_id, idx, enc_id)) { - DPU_ERROR("intf id %d already reserved\n", id); - return -ENAVAIL; - } - - global_state->intf_to_enc_id[idx] = enc_id; - return 0; -} - -static int _dpu_rm_reserve_intf_related_hw( - struct dpu_rm *rm, - struct dpu_global_state *global_state, - uint32_t enc_id, - struct dpu_encoder_hw_resources *hw_res) -{ - int i, ret = 0; - u32 id; - - for (i = 0; i < ARRAY_SIZE(hw_res->intfs); i++) { - if (hw_res->intfs[i] == INTF_MODE_NONE) - continue; - id = i + INTF_0; - ret = _dpu_rm_reserve_intf(rm, global_state, enc_id, id); - if (ret) - return ret; - } - - return ret; -} - static int _dpu_rm_make_reservation( struct dpu_rm *rm, struct dpu_global_state *global_state, @@ -517,11 +468,6 @@ static int _dpu_rm_make_reservation( return ret; } - ret = _dpu_rm_reserve_intf_related_hw(rm, global_state, enc->base.id, - &reqs->hw_res); - if (ret) - return ret; - return ret; } @@ -530,8 +476,6 @@ static int _dpu_rm_populate_requirements( struct dpu_rm_requirements *reqs, struct msm_display_topology req_topology) { - dpu_encoder_get_hw_resources(enc, &reqs->hw_res); - reqs->topology = req_topology; DRM_DEBUG_KMS("num_lm: %d num_enc: %d num_intf: %d\n", @@ -561,8 +505,6 @@ void dpu_rm_release(struct dpu_global_state *global_state, ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id); _dpu_rm_clear_mapping(global_state->ctl_to_enc_id, ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id); - _dpu_rm_clear_mapping(global_state->intf_to_enc_id, - ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id); } int dpu_rm_reserve( @@ -626,11 +568,6 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, hw_to_enc_id = global_state->ctl_to_enc_id; max_blks = ARRAY_SIZE(rm->ctl_blks); break; - case DPU_HW_BLK_INTF: - hw_blks = rm->intf_blks; - hw_to_enc_id = global_state->intf_to_enc_id; - max_blks = ARRAY_SIZE(rm->intf_blks); - break; case DPU_HW_BLK_DSPP: hw_blks = rm->dspp_blks; hw_to_enc_id = global_state->dspp_to_enc_id; @@ -656,3 +593,8 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, return num_blks; } + +struct dpu_hw_intf *dpu_rm_get_intf(struct dpu_rm *rm, enum dpu_intf intf_idx) +{ + return to_dpu_hw_intf(rm->intf_blks[intf_idx - INTF_0]); +} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h index 0f27759211b5d..ee50f6651b6e1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h @@ -84,5 +84,13 @@ void dpu_rm_release(struct dpu_global_state *global_state, int dpu_rm_get_assigned_resources(struct dpu_rm *rm, struct dpu_global_state *global_state, uint32_t enc_id, enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size); + +/** + * dpu_rm_get_intf - Return a struct dpu_hw_intf instance given it's index. + * @rm: DPU Resource Manager handle + * @intf_idx: INTF's index + */ +struct dpu_hw_intf *dpu_rm_get_intf(struct dpu_rm *rm, enum dpu_intf intf_idx); + #endif /* __DPU_RM_H__ */ From ae57fdf0f21768650a4de9e55a1df203adcb9956 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 22 Jan 2022 00:06:16 +0300 Subject: [PATCH 39/70] drm/msm/dpu: stop embedding dpu_hw_blk into dpu_hw_intf Now as dpu_hw_intf is not hanled by dpu_rm_get_assigned_resources, there is no point in embedding the (empty) struct dpu_hw_blk into dpu_hw_intf (and using typecasts between dpu_hw_blk and dpu_hw_intf). Drop it and use dpu_hw_intf directly. Signed-off-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220121210618.3482550-5-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 11 ----------- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 +++-------------- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 9 ++++++--- 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h index 3568be80dab51..230d122fa43bb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h @@ -78,7 +78,6 @@ struct dpu_hw_intf_ops { }; struct dpu_hw_intf { - struct dpu_hw_blk base; struct dpu_hw_blk_reg_map hw; /* intf */ @@ -90,16 +89,6 @@ struct dpu_hw_intf { struct dpu_hw_intf_ops ops; }; -/** - * to_dpu_hw_intf - convert base object dpu_hw_base to container - * @hw: Pointer to base hardware block - * return: Pointer to hardware block container - */ -static inline struct dpu_hw_intf *to_dpu_hw_intf(struct dpu_hw_blk *hw) -{ - return container_of(hw, struct dpu_hw_intf, base); -} - /** * dpu_hw_intf_init(): Initializes the intf driver for the passed * interface idx. diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 8df21a46308e5..96554e962e38b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -74,14 +74,8 @@ int dpu_rm_destroy(struct dpu_rm *rm) dpu_hw_ctl_destroy(hw); } } - for (i = 0; i < ARRAY_SIZE(rm->intf_blks); i++) { - struct dpu_hw_intf *hw; - - if (rm->intf_blks[i]) { - hw = to_dpu_hw_intf(rm->intf_blks[i]); - dpu_hw_intf_destroy(hw); - } - } + for (i = 0; i < ARRAY_SIZE(rm->hw_intf); i++) + dpu_hw_intf_destroy(rm->hw_intf[i]); return 0; } @@ -179,7 +173,7 @@ int dpu_rm_init(struct dpu_rm *rm, DPU_ERROR("failed intf object creation: err %d\n", rc); goto fail; } - rm->intf_blks[intf->id - INTF_0] = &hw->base; + rm->hw_intf[intf->id - INTF_0] = hw; } for (i = 0; i < cat->ctl_count; i++) { @@ -593,8 +587,3 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, return num_blks; } - -struct dpu_hw_intf *dpu_rm_get_intf(struct dpu_rm *rm, enum dpu_intf intf_idx) -{ - return to_dpu_hw_intf(rm->intf_blks[intf_idx - INTF_0]); -} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h index ee50f6651b6e1..9b13200a050a6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h @@ -18,14 +18,14 @@ struct dpu_global_state; * @pingpong_blks: array of pingpong hardware resources * @mixer_blks: array of layer mixer hardware resources * @ctl_blks: array of ctl hardware resources - * @intf_blks: array of intf hardware resources + * @hw_intf: array of intf hardware resources * @dspp_blks: array of dspp hardware resources */ struct dpu_rm { struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0]; struct dpu_hw_blk *mixer_blks[LM_MAX - LM_0]; struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0]; - struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0]; + struct dpu_hw_intf *hw_intf[INTF_MAX - INTF_0]; struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0]; struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0]; }; @@ -90,7 +90,10 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, * @rm: DPU Resource Manager handle * @intf_idx: INTF's index */ -struct dpu_hw_intf *dpu_rm_get_intf(struct dpu_rm *rm, enum dpu_intf intf_idx); +static inline struct dpu_hw_intf *dpu_rm_get_intf(struct dpu_rm *rm, enum dpu_intf intf_idx) +{ + return rm->hw_intf[intf_idx - INTF_0]; +} #endif /* __DPU_RM_H__ */ From 740828c73a36028f560e378f0007717bcfa27a02 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 22 Jan 2022 00:06:17 +0300 Subject: [PATCH 40/70] drm/msm/dpu: fix error handling in dpu_rm_init Using IS_ERR_OR_NULL() together with PTR_ERR() is a typical mistake. If the value is NULL, then the function will return 0 instead of a proper return code. Moreover none of dpu_hw_*_init() functions can return NULL. So, replace all dpu_rm_init()'s IS_ERR_OR_NULL() calls with IS_ERR(). Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220121210618.3482550-6-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 96554e962e38b..7497538adae15 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -109,7 +109,7 @@ int dpu_rm_init(struct dpu_rm *rm, continue; } hw = dpu_hw_lm_init(lm->id, mmio, cat); - if (IS_ERR_OR_NULL(hw)) { + if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed lm object creation: err %d\n", rc); goto fail; @@ -126,7 +126,7 @@ int dpu_rm_init(struct dpu_rm *rm, continue; } hw = dpu_hw_merge_3d_init(merge_3d->id, mmio, cat); - if (IS_ERR_OR_NULL(hw)) { + if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed merge_3d object creation: err %d\n", rc); @@ -144,7 +144,7 @@ int dpu_rm_init(struct dpu_rm *rm, continue; } hw = dpu_hw_pingpong_init(pp->id, mmio, cat); - if (IS_ERR_OR_NULL(hw)) { + if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed pingpong object creation: err %d\n", rc); @@ -168,7 +168,7 @@ int dpu_rm_init(struct dpu_rm *rm, continue; } hw = dpu_hw_intf_init(intf->id, mmio, cat); - if (IS_ERR_OR_NULL(hw)) { + if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed intf object creation: err %d\n", rc); goto fail; @@ -185,7 +185,7 @@ int dpu_rm_init(struct dpu_rm *rm, continue; } hw = dpu_hw_ctl_init(ctl->id, mmio, cat); - if (IS_ERR_OR_NULL(hw)) { + if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed ctl object creation: err %d\n", rc); goto fail; @@ -202,7 +202,7 @@ int dpu_rm_init(struct dpu_rm *rm, continue; } hw = dpu_hw_dspp_init(dspp->id, mmio, cat); - if (IS_ERR_OR_NULL(hw)) { + if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed dspp object creation: err %d\n", rc); goto fail; From 148e852f290fe8be9fa69953bee2f958befd65d4 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 14 Feb 2022 20:33:52 -0800 Subject: [PATCH 41/70] drm/msm/dpu: Add INTF_5 interrupts SC8180x has the eDP controller wired up to INTF_5, so add the interrupt register block for this interface to the list. Signed-off-by: Bjorn Andersson Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220215043353.1256754-1-bjorn.andersson@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 6 ++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index 27073fd49fee0..c515b7cf922c8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -23,6 +23,7 @@ #define MDP_INTF_2_OFF 0x6B000 #define MDP_INTF_3_OFF 0x6B800 #define MDP_INTF_4_OFF 0x6C000 +#define MDP_INTF_5_OFF 0x6C800 #define MDP_AD4_0_OFF 0x7C000 #define MDP_AD4_1_OFF 0x7D000 #define MDP_AD4_INTR_EN_OFF 0x41c @@ -93,6 +94,11 @@ static const struct dpu_intr_reg dpu_intr_set[] = { MDP_INTF_4_OFF+INTF_INTR_EN, MDP_INTF_4_OFF+INTF_INTR_STATUS }, + { + MDP_INTF_5_OFF+INTF_INTR_CLEAR, + MDP_INTF_5_OFF+INTF_INTR_EN, + MDP_INTF_5_OFF+INTF_INTR_STATUS + }, { MDP_AD4_0_OFF + MDP_AD4_INTR_CLEAR_OFF, MDP_AD4_0_OFF + MDP_AD4_INTR_EN_OFF, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h index 1ab75cccd1456..37379966d8ec5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h @@ -22,6 +22,7 @@ enum dpu_hw_intr_reg { MDP_INTF2_INTR, MDP_INTF3_INTR, MDP_INTF4_INTR, + MDP_INTF5_INTR, MDP_AD4_0_INTR, MDP_AD4_1_INTR, MDP_INTF0_7xxx_INTR, From f3af2d6ee9abb5e84466b10f6ed4a4b3e8281a17 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 16 Feb 2022 17:21:55 -0800 Subject: [PATCH 42/70] drm/msm/dpu: Add SC8180x to hw catalog Add SC8180x to the hardware catalog, for initial support for the platform. Due to limitations in the DP driver only one of the four DP interfaces is left enabled. The SC8180x platform supports the newly added DPU_INTF_WIDEBUS flag and the Windows-on-Snapdragon bootloader leaves the widebus bit set, so this is flagged appropriately to ensure widebus is disabled - for now. Signed-off-by: Rob Clark [bjorn: Reworked intf and irq definitions] Signed-off-by: Bjorn Andersson Reviewed-by: Dmitry Baryshkov --- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 129 ++++++++++++++++++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 + drivers/gpu/drm/msm/msm_drv.c | 1 + 4 files changed, 132 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index d3151ac4ca881..aa4d20762ccb8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -103,6 +103,17 @@ BIT(MDP_INTF3_INTR) | \ BIT(MDP_INTF4_INTR)) +#define IRQ_SC8180X_MASK (BIT(MDP_SSPP_TOP0_INTR) | \ + BIT(MDP_SSPP_TOP0_INTR2) | \ + BIT(MDP_SSPP_TOP0_HIST_INTR) | \ + BIT(MDP_INTF0_INTR) | \ + BIT(MDP_INTF1_INTR) | \ + BIT(MDP_INTF2_INTR) | \ + BIT(MDP_INTF3_INTR) | \ + BIT(MDP_INTF4_INTR) | \ + BIT(MDP_INTF5_INTR) | \ + BIT(MDP_AD4_0_INTR) | \ + BIT(MDP_AD4_1_INTR)) #define DEFAULT_PIXEL_RAM_SIZE (50 * 1024) #define DEFAULT_DPU_LINE_WIDTH 2048 @@ -254,6 +265,22 @@ static const struct dpu_caps sm8150_dpu_caps = { .max_vdeci_exp = MAX_VERT_DECIMATION, }; +static const struct dpu_caps sc8180x_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0xb, + .qseed_type = DPU_SSPP_SCALER_QSEED3, + .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ + .ubwc_version = DPU_HW_UBWC_VER_30, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 4096, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .max_hdeci_exp = MAX_HORZ_DECIMATION, + .max_vdeci_exp = MAX_VERT_DECIMATION, +}; + static const struct dpu_caps sm8250_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, @@ -351,6 +378,31 @@ static const struct dpu_mdp_cfg sc7180_mdp[] = { }, }; +static const struct dpu_mdp_cfg sc8180x_mdp[] = { + { + .name = "top_0", .id = MDP_TOP, + .base = 0x0, .len = 0x45C, + .features = 0, + .highest_bank_bit = 0x3, + .clk_ctrls[DPU_CLK_CTRL_VIG0] = { + .reg_off = 0x2AC, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG1] = { + .reg_off = 0x2B4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG2] = { + .reg_off = 0x2BC, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG3] = { + .reg_off = 0x2C4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA0] = { + .reg_off = 0x2AC, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_DMA1] = { + .reg_off = 0x2B4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .reg_off = 0x2BC, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .reg_off = 0x2C4, .bit_off = 8}, + }, +}; + static const struct dpu_mdp_cfg sm8250_mdp[] = { { .name = "top_0", .id = MDP_TOP, @@ -1027,6 +1079,16 @@ static const struct dpu_intf_cfg sc7280_intf[] = { INTF_BLK("intf_5", INTF_5, 0x39000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23), }; +static const struct dpu_intf_cfg sc8180x_intf[] = { + INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), + INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27), + INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 28, 29), + /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until this is supported */ + INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 999, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 30, 31), + INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 20, 21), + INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 22, 23), +}; + /************************************************************* * VBIF sub blocks config *************************************************************/ @@ -1168,6 +1230,10 @@ static const struct dpu_qos_lut_entry sm8150_qos_linear[] = { {.fl = 0, .lut = 0x0011222222223357 }, }; +static const struct dpu_qos_lut_entry sc8180x_qos_linear[] = { + {.fl = 4, .lut = 0x0000000000000357 }, +}; + static const struct dpu_qos_lut_entry sdm845_qos_macrotile[] = { {.fl = 10, .lut = 0x344556677}, {.fl = 11, .lut = 0x3344556677}, @@ -1181,6 +1247,10 @@ static const struct dpu_qos_lut_entry sc7180_qos_macrotile[] = { {.fl = 0, .lut = 0x0011223344556677}, }; +static const struct dpu_qos_lut_entry sc8180x_qos_macrotile[] = { + {.fl = 10, .lut = 0x0000000344556677}, +}; + static const struct dpu_qos_lut_entry msm8998_qos_nrt[] = { {.fl = 0, .lut = 0x0}, }; @@ -1322,6 +1392,33 @@ static const struct dpu_perf_cfg sm8150_perf_data = { .bw_inefficiency_factor = 120, }; +static const struct dpu_perf_cfg sc8180x_perf_data = { + .max_bw_low = 9600000, + .max_bw_high = 9600000, + .min_core_ib = 2400000, + .min_llcc_ib = 800000, + .min_dram_ib = 800000, + .danger_lut_tbl = {0xf, 0xffff, 0x0}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(sc8180x_qos_linear), + .entries = sc8180x_qos_linear + }, + {.nentry = ARRAY_SIZE(sc8180x_qos_macrotile), + .entries = sc8180x_qos_macrotile + }, + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), + .entries = sc7180_qos_nrt + }, + /* TODO: macrotile-qseed is different from macrotile */ + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; + static const struct dpu_perf_cfg sm8250_perf_data = { .max_bw_low = 13700000, .max_bw_high = 16600000, @@ -1504,6 +1601,37 @@ static void sm8150_cfg_init(struct dpu_mdss_cfg *dpu_cfg) }; } +/* + * sc8180x_cfg_init(): populate sc8180 dpu sub-blocks reg offsets + * and instance counts. + */ +static void sc8180x_cfg_init(struct dpu_mdss_cfg *dpu_cfg) +{ + *dpu_cfg = (struct dpu_mdss_cfg){ + .caps = &sc8180x_dpu_caps, + .mdp_count = ARRAY_SIZE(sc8180x_mdp), + .mdp = sc8180x_mdp, + .ctl_count = ARRAY_SIZE(sm8150_ctl), + .ctl = sm8150_ctl, + .sspp_count = ARRAY_SIZE(sdm845_sspp), + .sspp = sdm845_sspp, + .mixer_count = ARRAY_SIZE(sm8150_lm), + .mixer = sm8150_lm, + .pingpong_count = ARRAY_SIZE(sm8150_pp), + .pingpong = sm8150_pp, + .merge_3d_count = ARRAY_SIZE(sm8150_merge_3d), + .merge_3d = sm8150_merge_3d, + .intf_count = ARRAY_SIZE(sc8180x_intf), + .intf = sc8180x_intf, + .vbif_count = ARRAY_SIZE(sdm845_vbif), + .vbif = sdm845_vbif, + .reg_dma_count = 1, + .dma_cfg = sm8150_regdma, + .perf = sc8180x_perf_data, + .mdss_irqs = IRQ_SC8180X_MASK, + }; +} + /* * sm8250_cfg_init(): populate sm8250 dpu sub-blocks reg offsets * and instance counts. @@ -1567,6 +1695,7 @@ static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = { { .hw_rev = DPU_HW_VER_401, .cfg_init = sdm845_cfg_init}, { .hw_rev = DPU_HW_VER_500, .cfg_init = sm8150_cfg_init}, { .hw_rev = DPU_HW_VER_501, .cfg_init = sm8150_cfg_init}, + { .hw_rev = DPU_HW_VER_510, .cfg_init = sc8180x_cfg_init}, { .hw_rev = DPU_HW_VER_600, .cfg_init = sm8250_cfg_init}, { .hw_rev = DPU_HW_VER_620, .cfg_init = sc7180_cfg_init}, { .hw_rev = DPU_HW_VER_720, .cfg_init = sc7280_cfg_init}, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index c67a8e63171f2..2912ee0eb3051 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -39,6 +39,7 @@ #define DPU_HW_VER_410 DPU_HW_VER(4, 1, 0) /* sdm670 v1.0 */ #define DPU_HW_VER_500 DPU_HW_VER(5, 0, 0) /* sm8150 v1.0 */ #define DPU_HW_VER_501 DPU_HW_VER(5, 0, 1) /* sm8150 v2.0 */ +#define DPU_HW_VER_510 DPU_HW_VER(5, 1, 1) /* sc8180 */ #define DPU_HW_VER_600 DPU_HW_VER(6, 0, 0) /* sm8250 */ #define DPU_HW_VER_620 DPU_HW_VER(6, 2, 0) /* sc7180 v1.0 */ #define DPU_HW_VER_720 DPU_HW_VER(7, 2, 0) /* sc7280 */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 83a19bfe5f9cb..3118ccec1f1a3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1352,6 +1352,7 @@ const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,sdm845-dpu", }, { .compatible = "qcom,sc7180-dpu", }, { .compatible = "qcom,sc7280-dpu", }, + { .compatible = "qcom,sc8180x-dpu", }, { .compatible = "qcom,sm8150-dpu", }, { .compatible = "qcom,sm8250-dpu", }, {} diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index e85c010bd3294..5d153ec94fe97 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1439,6 +1439,7 @@ static const struct of_device_id dt_match[] = { { .compatible = "qcom,sdm845-mdss", .data = (void *)KMS_DPU }, { .compatible = "qcom,sc7180-mdss", .data = (void *)KMS_DPU }, { .compatible = "qcom,sc7280-mdss", .data = (void *)KMS_DPU }, + { .compatible = "qcom,sc8180x-mdss", .data = (void *)KMS_DPU }, { .compatible = "qcom,sm8150-mdss", .data = (void *)KMS_DPU }, { .compatible = "qcom,sm8250-mdss", .data = (void *)KMS_DPU }, {} From 7c175aa1cc9d5a98483fcb8588c58d0db17f73b4 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sat, 12 Feb 2022 03:38:11 +0300 Subject: [PATCH 43/70] drm/msm/dpu: Only create debugfs for PRIMARY minor dpu_kms_debugfs_init() is invoked for each minor being registered. Most of the files created are unrelated to the minor, so there's no reason to present them per minor. The exception to this is the DisplayPort code, which ends up invoking dp_debug_get() for each minor, each time associate the allocated object with dp->debug. As such dp_debug will create debugfs files in both the PRIMARY and the RENDER minor's debugfs directory, but only the last reference will be remembered. The only use of this reference today is in the cleanup path in dp_display_deinit_sub_modules() and the dp_debug_private object does outlive the debugfs entries in either case, so there doesn't seem to be any adverse effects of this, but per the code the current behavior is unexpected, so change it to only create debugfs files for the PRIMARY minor. Signed-off-by: Bjorn Andersson [DB: slightly change description and in-patch comment] Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220212003811.1818774-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 3118ccec1f1a3..764a315aba609 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -271,6 +271,10 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) if (!p) return -EINVAL; + /* Only create a set of debugfs for the primary node, ignore render nodes */ + if (minor->type != DRM_MINOR_PRIMARY) + return 0; + dev = dpu_kms->dev; priv = dev->dev_private; From 77e113351ffe49119ef322e9a2a0e65d57c6963b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 15 Feb 2022 17:53:06 +0300 Subject: [PATCH 44/70] drm/msm/dpu: drop unused access macros The access macros BLK_foo are not used by the code, drop them. Signed-off-by: Dmitry Baryshkov Reviewed-by: Bjorn Andersson Reviewed-by: Stephen Boyd Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20220215145306.3470924-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 2912ee0eb3051..2a5e3956ed4ad 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -785,22 +785,6 @@ struct dpu_mdss_hw_cfg_handler { void (*cfg_init)(struct dpu_mdss_cfg *dpu_cfg); }; -/* - * Access Macros - */ -#define BLK_MDP(s) ((s)->mdp) -#define BLK_CTL(s) ((s)->ctl) -#define BLK_VIG(s) ((s)->vig) -#define BLK_RGB(s) ((s)->rgb) -#define BLK_DMA(s) ((s)->dma) -#define BLK_CURSOR(s) ((s)->cursor) -#define BLK_MIXER(s) ((s)->mixer) -#define BLK_PINGPONG(s) ((s)->pingpong) -#define BLK_INTF(s) ((s)->intf) -#define BLK_AD(s) ((s)->ad) -#define BLK_DSPP(s) ((s)->dspp) -#define BLK_MERGE3d(s) ((s)->merge_3d) - /** * dpu_hw_catalog_init - dpu hardware catalog init API retrieves * hardcoded target specific catalog information in config structure From 1e0505a5a7a2fea243f8e6d7e13fcde65f9e41bc Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 17 Feb 2022 06:53:52 +0300 Subject: [PATCH 45/70] drm/msm/dpu: fix dp audio condition DP audio enablement code which is comparing intf_type, DRM_MODE_ENCODER_TMDS (= 2) with DRM_MODE_CONNECTOR_DisplayPort (= 10). Which would never succeed. Fix it to check for DRM_MODE_ENCODER_TMDS. Fixes: d13e36d7d222 ("drm/msm/dp: add audio support for Display Port on MSM") Reviewed-by: Abhinav Kumar Reviewed-by: Bjorn Andersson Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220217035358.465904-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index d442d4b9484fe..adbbcf02171f4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1069,7 +1069,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc) } - if (dpu_enc->disp_info.intf_type == DRM_MODE_CONNECTOR_DisplayPort && + if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_TMDS && dpu_enc->cur_master->hw_mdptop && dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select) dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select( From b7420739f112509eb8f7057e6eed627fb65ecd4a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 17 Feb 2022 06:53:53 +0300 Subject: [PATCH 46/70] drm/msm: move struct msm_display_info to dpu driver The msm_display_info structure is not used by the rest of msm driver, so move it into the dpu1 (dpu_encoder.h to be precise). Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220217035358.465904-3-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 18 ++++++++++++++++++ drivers/gpu/drm/msm/msm_drv.h | 18 ------------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index 722dd7db6bdf8..42db6ce12caf0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -18,6 +18,24 @@ #define IDLE_TIMEOUT (66 - 16/2) +/** + * struct msm_display_info - defines display properties + * @intf_type: DRM_MODE_ENCODER_ type + * @capabilities: Bitmask of display flags + * @num_of_h_tiles: Number of horizontal tiles in case of split interface + * @h_tile_instance: Controller instance used per tile. Number of elements is + * based on num_of_h_tiles + * @is_te_using_watchdog_timer: Boolean to indicate watchdog TE is + * used instead of panel TE in cmd mode panels + */ +struct msm_display_info { + int intf_type; + uint32_t capabilities; + uint32_t num_of_h_tiles; + uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; + bool is_te_using_watchdog_timer; +}; + /** * dpu_encoder_assign_crtc - Link the encoder to the crtc it's assigned to * @encoder: encoder pointer diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index d7574e6bd4e40..16f9e25ee19ed 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -109,24 +109,6 @@ struct msm_display_topology { u32 num_dspp; }; -/** - * struct msm_display_info - defines display properties - * @intf_type: DRM_MODE_ENCODER_ type - * @capabilities: Bitmask of display flags - * @num_of_h_tiles: Number of horizontal tiles in case of split interface - * @h_tile_instance: Controller instance used per tile. Number of elements is - * based on num_of_h_tiles - * @is_te_using_watchdog_timer: Boolean to indicate watchdog TE is - * used instead of panel TE in cmd mode panels - */ -struct msm_display_info { - int intf_type; - uint32_t capabilities; - uint32_t num_of_h_tiles; - uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; - bool is_te_using_watchdog_timer; -}; - /* Commit/Event thread specific structure */ struct msm_drm_thread { struct drm_device *dev; From b78f30a5c8a396ca31a905982c8cd955cd35807e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 17 Feb 2022 06:53:54 +0300 Subject: [PATCH 47/70] drm/msm/dpu: remove msm_dp cached in dpu_encoder_virt Stop caching msm_dp instance in dpu_encoder_virt since it's not used now. Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display enable and disable") Reviewed-by: Abhinav Kumar Reviewed-by: Bjorn Andersson Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220217035358.465904-4-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index adbbcf02171f4..1b0829a152b37 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -168,7 +168,6 @@ enum dpu_enc_rc_states { * @vsync_event_work: worker to handle vsync event for autorefresh * @topology: topology of the display * @idle_timeout: idle timeout duration in milliseconds - * @dp: msm_dp pointer, for DP encoders */ struct dpu_encoder_virt { struct drm_encoder base; @@ -207,8 +206,6 @@ struct dpu_encoder_virt { struct msm_display_topology topology; u32 idle_timeout; - - struct msm_dp *dp; }; #define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, base) @@ -2093,8 +2090,6 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, timer_setup(&dpu_enc->vsync_event_timer, dpu_encoder_vsync_event_handler, 0); - else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) - dpu_enc->dp = priv->dp[disp_info->h_tile_instance[0]]; INIT_DELAYED_WORK(&dpu_enc->delayed_off_work, dpu_encoder_off_work); From 66175f1942749a7b5f0808fad44245bd599f1701 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 17 Feb 2022 06:53:55 +0300 Subject: [PATCH 48/70] drm/msm/dpu: drop bus_scaling_client field We do not use MSM bus client, so drop bus_scaling_client field from dpu_encoder_virt. Reviewed-by: Abhinav Kumar Reviewed-by: Bjorn Andersson Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220217035358.465904-5-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1b0829a152b37..3d5fd73950f16 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -127,7 +127,6 @@ enum dpu_enc_rc_states { * Virtual encoder registers itself with the DRM Framework as the encoder. * @base: drm_encoder base class for registration with DRM * @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes - * @bus_scaling_client: Client handle to the bus scaling interface * @enabled: True if the encoder is active, protected by enc_lock * @num_phys_encs: Actual number of physical encoders contained. * @phys_encs: Container of physical encoders managed. @@ -172,7 +171,6 @@ enum dpu_enc_rc_states { struct dpu_encoder_virt { struct drm_encoder base; spinlock_t enc_spinlock; - uint32_t bus_scaling_client; bool enabled; From 3177589c6e934494e72a2d5934539a836b986390 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 17 Feb 2022 06:53:56 +0300 Subject: [PATCH 49/70] drm/msm/dpu: encoder: drop unused mode_fixup callback Both cmd and vid backends provide useless mode_fixup() callback. Drop it. Reviewed-by: Bjorn Andersson Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220217035358.465904-6-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 ---- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 4 ---- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 10 ---------- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 -------------- 4 files changed, 32 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 3d5fd73950f16..c7eb070bd44e4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -582,10 +582,6 @@ static int dpu_encoder_virt_atomic_check( if (phys->ops.atomic_check) ret = phys->ops.atomic_check(phys, crtc_state, conn_state); - else if (phys->ops.mode_fixup) - if (!phys->ops.mode_fixup(phys, mode, adj_mode)) - ret = -EINVAL; - if (ret) { DPU_ERROR_ENC(dpu_enc, "mode unsupported, phys idx %d\n", i); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index 42febfce79c73..6eb2eb4ecb3d6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -84,7 +84,6 @@ struct dpu_encoder_virt_ops { * @is_master: Whether this phys_enc is the current master * encoder. Can be switched at enable time. Based * on split_role and current mode (CMD/VID). - * @mode_fixup: DRM Call. Fixup a DRM mode. * @mode_set: DRM Call. Set a DRM mode. * This likely caches the mode, for use at enable. * @enable: DRM Call. Enable a DRM mode. @@ -114,9 +113,6 @@ struct dpu_encoder_phys_ops { struct dentry *debugfs_root); void (*prepare_commit)(struct dpu_encoder_phys *encoder); bool (*is_master)(struct dpu_encoder_phys *encoder); - bool (*mode_fixup)(struct dpu_encoder_phys *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); void (*mode_set)(struct dpu_encoder_phys *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index 7d2beea9cc4e8..96b9d57b8b6cf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -45,15 +45,6 @@ static bool dpu_encoder_phys_cmd_is_master(struct dpu_encoder_phys *phys_enc) return (phys_enc->split_role != ENC_ROLE_SLAVE); } -static bool dpu_encoder_phys_cmd_mode_fixup( - struct dpu_encoder_phys *phys_enc, - const struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) -{ - DPU_DEBUG_CMDENC(to_dpu_encoder_phys_cmd(phys_enc), "\n"); - return true; -} - static void _dpu_encoder_phys_cmd_update_intf_cfg( struct dpu_encoder_phys *phys_enc) { @@ -725,7 +716,6 @@ static void dpu_encoder_phys_cmd_init_ops( ops->prepare_commit = dpu_encoder_phys_cmd_prepare_commit; ops->is_master = dpu_encoder_phys_cmd_is_master; ops->mode_set = dpu_encoder_phys_cmd_mode_set; - ops->mode_fixup = dpu_encoder_phys_cmd_mode_fixup; ops->enable = dpu_encoder_phys_cmd_enable; ops->disable = dpu_encoder_phys_cmd_disable; ops->destroy = dpu_encoder_phys_cmd_destroy; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index db6a9b896e426..7e837ca63095f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -225,19 +225,6 @@ static void programmable_fetch_config(struct dpu_encoder_phys *phys_enc, spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); } -static bool dpu_encoder_phys_vid_mode_fixup( - struct dpu_encoder_phys *phys_enc, - const struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) -{ - DPU_DEBUG_VIDENC(phys_enc, "\n"); - - /* - * Modifying mode has consequences when the mode comes back to us - */ - return true; -} - static void dpu_encoder_phys_vid_setup_timing_engine( struct dpu_encoder_phys *phys_enc) { @@ -669,7 +656,6 @@ static void dpu_encoder_phys_vid_init_ops(struct dpu_encoder_phys_ops *ops) { ops->is_master = dpu_encoder_phys_vid_is_master; ops->mode_set = dpu_encoder_phys_vid_mode_set; - ops->mode_fixup = dpu_encoder_phys_vid_mode_fixup; ops->enable = dpu_encoder_phys_vid_enable; ops->disable = dpu_encoder_phys_vid_disable; ops->destroy = dpu_encoder_phys_vid_destroy; From 764332bf96244cbc8baf08aa35844b29106da312 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 17 Feb 2022 06:53:57 +0300 Subject: [PATCH 50/70] drm/msm/dpu: switch dpu_encoder to use atomic_mode_set Make dpu_encoder use atomic_mode_set to receive connector and CRTC states as arguments rather than finding connector and CRTC by manually looping through the respective lists. Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220217035358.465904-7-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 37 +++++-------------- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 8 ++-- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 18 ++------- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 ++----- 4 files changed, 21 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index c7eb070bd44e4..df6b1de3edf7b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -927,16 +927,13 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, return 0; } -static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, - struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) +static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { struct dpu_encoder_virt *dpu_enc; struct msm_drm_private *priv; struct dpu_kms *dpu_kms; - struct list_head *connector_list; - struct drm_connector *conn = NULL, *conn_iter; - struct drm_crtc *drm_crtc; struct dpu_crtc_state *cstate; struct dpu_global_state *global_state; struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC]; @@ -956,7 +953,6 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, priv = drm_enc->dev->dev_private; dpu_kms = to_dpu_kms(priv->kms); - connector_list = &dpu_kms->dev->mode_config.connector_list; global_state = dpu_kms_get_existing_global_state(dpu_kms); if (IS_ERR_OR_NULL(global_state)) { @@ -966,22 +962,6 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, trace_dpu_enc_mode_set(DRMID(drm_enc)); - list_for_each_entry(conn_iter, connector_list, head) - if (conn_iter->encoder == drm_enc) - conn = conn_iter; - - if (!conn) { - DPU_ERROR_ENC(dpu_enc, "failed to find attached connector\n"); - return; - } else if (!conn->state) { - DPU_ERROR_ENC(dpu_enc, "invalid connector state\n"); - return; - } - - drm_for_each_crtc(drm_crtc, drm_enc->dev) - if (drm_crtc->state->encoder_mask & drm_encoder_mask(drm_enc)) - break; - /* Query resource that have been reserved in atomic check step. */ num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp, @@ -998,7 +978,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i]) : NULL; - cstate = to_dpu_crtc_state(drm_crtc->state); + cstate = to_dpu_crtc_state(crtc_state); for (i = 0; i < num_lm; i++) { int ctl_idx = (i < num_ctl) ? i : (num_ctl-1); @@ -1037,9 +1017,10 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, return; } - phys->connector = conn->state->connector; - if (phys->ops.mode_set) - phys->ops.mode_set(phys, mode, adj_mode); + phys->connector = conn_state->connector; + phys->cached_mode = crtc_state->adjusted_mode; + if (phys->ops.atomic_mode_set) + phys->ops.atomic_mode_set(phys, crtc_state, conn_state); } } @@ -2049,7 +2030,7 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t) } static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { - .mode_set = dpu_encoder_virt_mode_set, + .atomic_mode_set = dpu_encoder_virt_atomic_mode_set, .disable = dpu_encoder_virt_disable, .enable = dpu_encoder_virt_enable, .atomic_check = dpu_encoder_virt_atomic_check, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index 6eb2eb4ecb3d6..918989bc91b74 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -84,7 +84,7 @@ struct dpu_encoder_virt_ops { * @is_master: Whether this phys_enc is the current master * encoder. Can be switched at enable time. Based * on split_role and current mode (CMD/VID). - * @mode_set: DRM Call. Set a DRM mode. + * @atomic_mode_set: DRM Call. Set a DRM mode. * This likely caches the mode, for use at enable. * @enable: DRM Call. Enable a DRM mode. * @disable: DRM Call. Disable mode. @@ -113,9 +113,9 @@ struct dpu_encoder_phys_ops { struct dentry *debugfs_root); void (*prepare_commit)(struct dpu_encoder_phys *encoder); bool (*is_master)(struct dpu_encoder_phys *encoder); - void (*mode_set)(struct dpu_encoder_phys *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); + void (*atomic_mode_set)(struct dpu_encoder_phys *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state); void (*enable)(struct dpu_encoder_phys *encoder); void (*disable)(struct dpu_encoder_phys *encoder); int (*atomic_check)(struct dpu_encoder_phys *encoder, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index 96b9d57b8b6cf..56c1bd2201102 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -135,23 +135,13 @@ static void dpu_encoder_phys_cmd_underrun_irq(void *arg, int irq_idx) phys_enc); } -static void dpu_encoder_phys_cmd_mode_set( +static void dpu_encoder_phys_cmd_atomic_mode_set( struct dpu_encoder_phys *phys_enc, - struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { - struct dpu_encoder_phys_cmd *cmd_enc = - to_dpu_encoder_phys_cmd(phys_enc); struct dpu_encoder_irq *irq; - if (!mode || !adj_mode) { - DPU_ERROR("invalid args\n"); - return; - } - phys_enc->cached_mode = *adj_mode; - DPU_DEBUG_CMDENC(cmd_enc, "caching mode:\n"); - drm_mode_debug_printmodeline(adj_mode); - irq = &phys_enc->irq[INTR_IDX_CTL_START]; irq->irq_idx = phys_enc->hw_ctl->caps->intr_start; @@ -715,7 +705,7 @@ static void dpu_encoder_phys_cmd_init_ops( { ops->prepare_commit = dpu_encoder_phys_cmd_prepare_commit; ops->is_master = dpu_encoder_phys_cmd_is_master; - ops->mode_set = dpu_encoder_phys_cmd_mode_set; + ops->atomic_mode_set = dpu_encoder_phys_cmd_atomic_mode_set; ops->enable = dpu_encoder_phys_cmd_enable; ops->disable = dpu_encoder_phys_cmd_disable; ops->destroy = dpu_encoder_phys_cmd_destroy; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index 7e837ca63095f..f49f42e70b29f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -348,19 +348,13 @@ static bool dpu_encoder_phys_vid_needs_single_flush( return phys_enc->split_role != ENC_ROLE_SOLO; } -static void dpu_encoder_phys_vid_mode_set( +static void dpu_encoder_phys_vid_atomic_mode_set( struct dpu_encoder_phys *phys_enc, - struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { struct dpu_encoder_irq *irq; - if (adj_mode) { - phys_enc->cached_mode = *adj_mode; - drm_mode_debug_printmodeline(adj_mode); - DPU_DEBUG_VIDENC(phys_enc, "caching mode:\n"); - } - irq = &phys_enc->irq[INTR_IDX_VSYNC]; irq->irq_idx = phys_enc->hw_intf->cap->intr_vsync; @@ -655,7 +649,7 @@ static int dpu_encoder_phys_vid_get_frame_count( static void dpu_encoder_phys_vid_init_ops(struct dpu_encoder_phys_ops *ops) { ops->is_master = dpu_encoder_phys_vid_is_master; - ops->mode_set = dpu_encoder_phys_vid_mode_set; + ops->atomic_mode_set = dpu_encoder_phys_vid_atomic_mode_set; ops->enable = dpu_encoder_phys_vid_enable; ops->disable = dpu_encoder_phys_vid_disable; ops->destroy = dpu_encoder_phys_vid_destroy; From 6b6921e5537d0f57726394b297fb2f3ca592b4dc Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 17 Feb 2022 06:53:58 +0300 Subject: [PATCH 51/70] drm/msm/dpu: pull connector from dpu_encoder_phys to dpu_encoder_virt All physical encoders used by virtual encoder share the same connector, so pull the connector field from dpu_encoder_phys into dpu_encoder_virt structure. Otherwise code suggests that different phys_encs can have different connectors. Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220217035358.465904-8-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 11 ++++++----- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 -- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index df6b1de3edf7b..3940b9c6323be 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -143,6 +143,7 @@ enum dpu_enc_rc_states { * link between encoder/crtc. However in this case we need * to track crtc in the disable() hook which is called * _after_ encoder_mask is cleared. + * @connector: If a mode is set, cached pointer to the active connector * @crtc_kickoff_cb: Callback into CRTC that will flush & start * all CTL paths * @crtc_kickoff_cb_data: Opaque user data given to crtc_kickoff_cb @@ -183,6 +184,7 @@ struct dpu_encoder_virt { bool intfs_swapped; struct drm_crtc *crtc; + struct drm_connector *connector; struct dentry *debugfs_root; struct mutex enc_lock; @@ -990,6 +992,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, cstate->num_mixers = num_lm; + dpu_enc->connector = conn_state->connector; + for (i = 0; i < dpu_enc->num_phys_encs; i++) { struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; @@ -1017,7 +1021,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, return; } - phys->connector = conn_state->connector; phys->cached_mode = crtc_state->adjusted_mode; if (phys->ops.atomic_mode_set) phys->ops.atomic_mode_set(phys, crtc_state, conn_state); @@ -1051,7 +1054,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc) if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI && !WARN_ON(dpu_enc->num_phys_encs == 0)) { - unsigned bpc = dpu_enc->phys_encs[0]->connector->display_info.bpc; + unsigned bpc = dpu_enc->connector->display_info.bpc; for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { if (!dpu_enc->hw_pp[i]) continue; @@ -1150,9 +1153,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_STOP); - for (i = 0; i < dpu_enc->num_phys_encs; i++) { - dpu_enc->phys_encs[i]->connector = NULL; - } + dpu_enc->connector = NULL; DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n"); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index 918989bc91b74..fa8493ac0340a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -173,7 +173,6 @@ struct dpu_encoder_irq { * tied to a specific panel / sub-panel. Abstract type, sub-classed by * phys_vid or phys_cmd for video mode or command mode encs respectively. * @parent: Pointer to the containing virtual encoder - * @connector: If a mode is set, cached pointer to the active connector * @ops: Operations exposed to the virtual encoder * @parent_ops: Callbacks exposed by the parent to the phys_enc * @hw_mdptop: Hardware interface to the top registers @@ -202,7 +201,6 @@ struct dpu_encoder_irq { */ struct dpu_encoder_phys { struct drm_encoder *parent; - struct drm_connector *connector; struct dpu_encoder_phys_ops ops; const struct dpu_encoder_virt_ops *parent_ops; struct dpu_hw_mdp *hw_mdptop; From 5752c921d267101e1abfc74a27a003b5c04e72bb Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 17 Feb 2022 08:55:25 +0300 Subject: [PATCH 52/70] drm/msm/dpu: simplify clocks handling DPU driver contains code to parse clock items from device tree into special data struct and then enable/disable/set rate for the clocks using that data struct. However the DPU driver itself uses only parsing and enabling/disabling part (the rate setting is used by DP driver). Move this implementation to the DP driver (which actually uses rate setting) and replace hand-coded enable/disable/get loops in the DPU with the respective clk_bulk operations. Put operation is removed completely because, it is handled using devres instead. DP implementation is unchanged for now. Tested-by: Jessica Zhang # RB3 (sdm845) and RB5 (qrb5165) Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220217055529.499829-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/Makefile | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 23 ++----- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h | 6 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 46 +++---------- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 +- drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 26 +++---- .../dpu1/dpu_io_util.c => dp/dp_clk_util.c} | 69 +------------------ .../dpu1/dpu_io_util.h => dp/dp_clk_util.h} | 8 +-- drivers/gpu/drm/msm/dp/dp_parser.h | 2 +- 9 files changed, 36 insertions(+), 150 deletions(-) rename drivers/gpu/drm/msm/{disp/dpu1/dpu_io_util.c => dp/dp_clk_util.c} (61%) rename drivers/gpu/drm/msm/{disp/dpu1/dpu_io_util.h => dp/dp_clk_util.h} (85%) diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 03ab55c37beb6..a44abf0a76601 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -66,7 +66,6 @@ msm-y := \ disp/dpu1/dpu_hw_top.o \ disp/dpu1/dpu_hw_util.o \ disp/dpu1/dpu_hw_vbif.o \ - disp/dpu1/dpu_io_util.o \ disp/dpu1/dpu_kms.o \ disp/dpu1/dpu_mdss.o \ disp/dpu1/dpu_plane.o \ @@ -102,6 +101,7 @@ msm-$(CONFIG_DRM_MSM_GPU_STATE) += adreno/a6xx_gpu_state.o msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_catalog.o \ + dp/dp_clk_util.o \ dp/dp_ctrl.o \ dp/dp_display.o \ dp/dp_drm.o \ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 60fe06018581c..a7492dd6ed654 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -284,17 +284,6 @@ void dpu_core_perf_crtc_release_bw(struct drm_crtc *crtc) } } -static int _dpu_core_perf_set_core_clk_rate(struct dpu_kms *kms, u64 rate) -{ - struct dss_clk *core_clk = kms->perf.core_clk; - - if (core_clk->max_rate && (rate > core_clk->max_rate)) - rate = core_clk->max_rate; - - core_clk->rate = rate; - return dev_pm_opp_set_rate(&kms->pdev->dev, core_clk->rate); -} - static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms) { u64 clk_rate = kms->perf.perf_tune.min_core_clk; @@ -306,7 +295,7 @@ static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms) dpu_cstate = to_dpu_crtc_state(crtc->state); clk_rate = max(dpu_cstate->new_perf.core_clk_rate, clk_rate); - clk_rate = clk_round_rate(kms->perf.core_clk->clk, + clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate); } } @@ -405,10 +394,10 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc, trace_dpu_core_perf_update_clk(kms->dev, stop_req, clk_rate); - ret = _dpu_core_perf_set_core_clk_rate(kms, clk_rate); + clk_rate = min(clk_rate, kms->perf.max_core_clk_rate); + ret = dev_pm_opp_set_rate(&kms->pdev->dev, clk_rate); if (ret) { - DPU_ERROR("failed to set %s clock rate %llu\n", - kms->perf.core_clk->clk_name, clk_rate); + DPU_ERROR("failed to set core clock rate %llu\n", clk_rate); return ret; } @@ -529,13 +518,13 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf) int dpu_core_perf_init(struct dpu_core_perf *perf, struct drm_device *dev, struct dpu_mdss_cfg *catalog, - struct dss_clk *core_clk) + struct clk *core_clk) { perf->dev = dev; perf->catalog = catalog; perf->core_clk = core_clk; - perf->max_core_clk_rate = core_clk->max_rate; + perf->max_core_clk_rate = clk_get_rate(core_clk); if (!perf->max_core_clk_rate) { DPU_DEBUG("optional max core clk rate, use default\n"); perf->max_core_clk_rate = DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h index cf4b9b5964c6c..8dfcc6db71766 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h @@ -56,7 +56,7 @@ struct dpu_core_perf_tune { * @dev: Pointer to drm device * @debugfs_root: top level debug folder * @catalog: Pointer to catalog configuration - * @core_clk: Pointer to core clock structure + * @core_clk: Pointer to the core clock * @core_clk_rate: current core clock rate * @max_core_clk_rate: maximum allowable core clock rate * @perf_tune: debug control for performance tuning @@ -69,7 +69,7 @@ struct dpu_core_perf { struct drm_device *dev; struct dentry *debugfs_root; struct dpu_mdss_cfg *catalog; - struct dss_clk *core_clk; + struct clk *core_clk; u64 core_clk_rate; u64 max_core_clk_rate; struct dpu_core_perf_tune perf_tune; @@ -120,7 +120,7 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf); int dpu_core_perf_init(struct dpu_core_perf *perf, struct drm_device *dev, struct dpu_mdss_cfg *catalog, - struct dss_clk *core_clk); + struct clk *core_clk); struct dpu_kms; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 764a315aba609..d4c023b9228c4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1002,29 +1002,15 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms) return 0; } -static struct dss_clk *_dpu_kms_get_clk(struct dpu_kms *dpu_kms, - char *clock_name) -{ - struct dss_module_power *mp = &dpu_kms->mp; - int i; - - for (i = 0; i < mp->num_clk; i++) { - if (!strcmp(mp->clk_config[i].clk_name, clock_name)) - return &mp->clk_config[i]; - } - - return NULL; -} - u64 dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name) { - struct dss_clk *clk; + struct clk *clk; - clk = _dpu_kms_get_clk(dpu_kms, clock_name); + clk = msm_clk_bulk_get_clock(dpu_kms->clocks, dpu_kms->num_clocks, clock_name); if (!clk) return -EINVAL; - return clk_get_rate(clk->clk); + return clk_get_rate(clk); } static int dpu_kms_hw_init(struct msm_kms *kms) @@ -1136,7 +1122,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) } rc = dpu_core_perf_init(&dpu_kms->perf, dev, dpu_kms->catalog, - _dpu_kms_get_clk(dpu_kms, "core")); + msm_clk_bulk_get_clock(dpu_kms->clocks, dpu_kms->num_clocks, "core")); if (rc) { DPU_ERROR("failed to init perf %d\n", rc); goto perf_err; @@ -1223,7 +1209,6 @@ static int dpu_bind(struct device *dev, struct device *master, void *data) struct platform_device *pdev = to_platform_device(dev); struct drm_device *ddev = priv->dev; struct dpu_kms *dpu_kms; - struct dss_module_power *mp; int ret = 0; dpu_kms = devm_kzalloc(&pdev->dev, sizeof(*dpu_kms), GFP_KERNEL); @@ -1240,12 +1225,12 @@ static int dpu_bind(struct device *dev, struct device *master, void *data) return ret; } - mp = &dpu_kms->mp; - ret = msm_dss_parse_clock(pdev, mp); - if (ret) { + ret = devm_clk_bulk_get_all(&pdev->dev, &dpu_kms->clocks); + if (ret < 0) { DPU_ERROR("failed to parse clocks, ret=%d\n", ret); return ret; } + dpu_kms->num_clocks = ret; platform_set_drvdata(pdev, dpu_kms); @@ -1269,11 +1254,6 @@ static void dpu_unbind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); - struct dss_module_power *mp = &dpu_kms->mp; - - msm_dss_put_clk(mp->clk_config, mp->num_clk); - devm_kfree(&pdev->dev, mp->clk_config); - mp->num_clk = 0; if (dpu_kms->rpm_enabled) pm_runtime_disable(&pdev->dev); @@ -1297,21 +1277,18 @@ static int dpu_dev_remove(struct platform_device *pdev) static int __maybe_unused dpu_runtime_suspend(struct device *dev) { - int i, rc = -1; + int i; struct platform_device *pdev = to_platform_device(dev); struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); - struct dss_module_power *mp = &dpu_kms->mp; /* Drop the performance state vote */ dev_pm_opp_set_rate(dev, 0); - rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false); - if (rc) - DPU_ERROR("clock disable failed rc:%d\n", rc); + clk_bulk_disable_unprepare(dpu_kms->num_clocks, dpu_kms->clocks); for (i = 0; i < dpu_kms->num_paths; i++) icc_set_bw(dpu_kms->path[i], 0, 0); - return rc; + return 0; } static int __maybe_unused dpu_runtime_resume(struct device *dev) @@ -1321,7 +1298,6 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev) struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct drm_encoder *encoder; struct drm_device *ddev; - struct dss_module_power *mp = &dpu_kms->mp; int i; ddev = dpu_kms->dev; @@ -1331,7 +1307,7 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev) for (i = 0; i < dpu_kms->num_paths; i++) icc_set_bw(dpu_kms->path[i], 0, Bps_to_icc(MIN_IB_BW)); - rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true); + rc = clk_bulk_prepare_enable(dpu_kms->num_clocks, dpu_kms->clocks); if (rc) { DPU_ERROR("clock enable failed rc:%d\n", rc); return rc; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 3f518c809e333..779e7bd01efde 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -21,7 +21,6 @@ #include "dpu_hw_lm.h" #include "dpu_hw_interrupts.h" #include "dpu_hw_top.h" -#include "dpu_io_util.h" #include "dpu_rm.h" #include "dpu_core_perf.h" @@ -113,7 +112,8 @@ struct dpu_kms { struct platform_device *pdev; bool rpm_enabled; - struct dss_module_power mp; + struct clk_bulk_data *clocks; + size_t num_clocks; /* reference count bandwidth requests, so we know when we can * release bandwidth. Each atomic update increments, and frame- diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c index 131c1f1a869c1..25b0fe67ea9c6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -29,7 +29,8 @@ struct dpu_irq_controller { struct dpu_mdss { struct msm_mdss base; void __iomem *mmio; - struct dss_module_power mp; + struct clk_bulk_data *clocks; + size_t num_clocks; struct dpu_irq_controller irq_controller; }; @@ -136,10 +137,9 @@ static void _dpu_mdss_irq_domain_fini(struct dpu_mdss *dpu_mdss) static int dpu_mdss_enable(struct msm_mdss *mdss) { struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss); - struct dss_module_power *mp = &dpu_mdss->mp; int ret; - ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true); + ret = clk_bulk_prepare_enable(dpu_mdss->num_clocks, dpu_mdss->clocks); if (ret) { DPU_ERROR("clock enable failed, ret:%d\n", ret); return ret; @@ -174,21 +174,16 @@ static int dpu_mdss_enable(struct msm_mdss *mdss) static int dpu_mdss_disable(struct msm_mdss *mdss) { struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss); - struct dss_module_power *mp = &dpu_mdss->mp; - int ret; - ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false); - if (ret) - DPU_ERROR("clock disable failed, ret:%d\n", ret); + clk_bulk_disable_unprepare(dpu_mdss->num_clocks, dpu_mdss->clocks); - return ret; + return 0; } static void dpu_mdss_destroy(struct msm_mdss *mdss) { struct platform_device *pdev = to_platform_device(mdss->dev); struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss); - struct dss_module_power *mp = &dpu_mdss->mp; int irq; pm_runtime_suspend(mdss->dev); @@ -196,8 +191,6 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss) _dpu_mdss_irq_domain_fini(dpu_mdss); irq = platform_get_irq(pdev, 0); irq_set_chained_handler_and_data(irq, NULL, NULL); - msm_dss_put_clk(mp->clk_config, mp->num_clk); - devm_kfree(&pdev->dev, mp->clk_config); if (dpu_mdss->mmio) devm_iounmap(&pdev->dev, dpu_mdss->mmio); @@ -214,7 +207,6 @@ int dpu_mdss_init(struct platform_device *pdev) { struct msm_drm_private *priv = platform_get_drvdata(pdev); struct dpu_mdss *dpu_mdss; - struct dss_module_power *mp; int ret; int irq; @@ -228,12 +220,12 @@ int dpu_mdss_init(struct platform_device *pdev) DRM_DEBUG("mapped mdss address space @%pK\n", dpu_mdss->mmio); - mp = &dpu_mdss->mp; - ret = msm_dss_parse_clock(pdev, mp); - if (ret) { + ret = devm_clk_bulk_get_all(&pdev->dev, &dpu_mdss->clocks); + if (ret < 0) { DPU_ERROR("failed to parse clocks, ret=%d\n", ret); goto clk_parse_err; } + dpu_mdss->num_clocks = ret; dpu_mdss->base.dev = &pdev->dev; dpu_mdss->base.funcs = &mdss_funcs; @@ -260,9 +252,7 @@ int dpu_mdss_init(struct platform_device *pdev) irq_error: _dpu_mdss_irq_domain_fini(dpu_mdss); irq_domain_error: - msm_dss_put_clk(mp->clk_config, mp->num_clk); clk_parse_err: - devm_kfree(&pdev->dev, mp->clk_config); if (dpu_mdss->mmio) devm_iounmap(&pdev->dev, dpu_mdss->mmio); dpu_mdss->mmio = NULL; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c b/drivers/gpu/drm/msm/dp/dp_clk_util.c similarity index 61% rename from drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c rename to drivers/gpu/drm/msm/dp/dp_clk_util.c index 078afc5f58820..44a4fc59ff31b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +++ b/drivers/gpu/drm/msm/dp/dp_clk_util.c @@ -11,7 +11,7 @@ #include -#include "dpu_io_util.h" +#include "dp_clk_util.h" void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk) { @@ -118,70 +118,3 @@ int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable) return rc; } - -int msm_dss_parse_clock(struct platform_device *pdev, - struct dss_module_power *mp) -{ - u32 i, rc = 0; - const char *clock_name; - int num_clk = 0; - - if (!pdev || !mp) - return -EINVAL; - - mp->num_clk = 0; - num_clk = of_property_count_strings(pdev->dev.of_node, "clock-names"); - if (num_clk <= 0) { - pr_debug("clocks are not defined\n"); - return 0; - } - - mp->clk_config = devm_kcalloc(&pdev->dev, - num_clk, sizeof(struct dss_clk), - GFP_KERNEL); - if (!mp->clk_config) - return -ENOMEM; - - for (i = 0; i < num_clk; i++) { - rc = of_property_read_string_index(pdev->dev.of_node, - "clock-names", i, - &clock_name); - if (rc) { - DRM_DEV_ERROR(&pdev->dev, "Failed to get clock name for %d\n", - i); - break; - } - strlcpy(mp->clk_config[i].clk_name, clock_name, - sizeof(mp->clk_config[i].clk_name)); - - mp->clk_config[i].type = DSS_CLK_AHB; - } - - rc = msm_dss_get_clk(&pdev->dev, mp->clk_config, num_clk); - if (rc) { - DRM_DEV_ERROR(&pdev->dev, "Failed to get clock refs %d\n", rc); - goto err; - } - - rc = of_clk_set_defaults(pdev->dev.of_node, false); - if (rc) { - DRM_DEV_ERROR(&pdev->dev, "Failed to set clock defaults %d\n", rc); - goto err; - } - - for (i = 0; i < num_clk; i++) { - u32 rate = clk_get_rate(mp->clk_config[i].clk); - if (!rate) - continue; - mp->clk_config[i].rate = rate; - mp->clk_config[i].type = DSS_CLK_PCLK; - mp->clk_config[i].max_rate = rate; - } - - mp->num_clk = num_clk; - return 0; - -err: - msm_dss_put_clk(mp->clk_config, num_clk); - return rc; -} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h b/drivers/gpu/drm/msm/dp/dp_clk_util.h similarity index 85% rename from drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h rename to drivers/gpu/drm/msm/dp/dp_clk_util.h index e6b5c772fa3bc..067bf87f3d972 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +++ b/drivers/gpu/drm/msm/dp/dp_clk_util.h @@ -2,8 +2,8 @@ /* Copyright (c) 2012, 2017-2018, The Linux Foundation. All rights reserved. */ -#ifndef __DPU_IO_UTIL_H__ -#define __DPU_IO_UTIL_H__ +#ifndef __DP_CLK_UTIL_H__ +#define __DP_CLK_UTIL_H__ #include #include @@ -35,6 +35,4 @@ int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk); void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk); int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk); int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable); -int msm_dss_parse_clock(struct platform_device *pdev, - struct dss_module_power *mp); -#endif /* __DPU_IO_UTIL_H__ */ +#endif /* __DP_CLK_UTIL_H__ */ diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 3172da0894216..094b39bfed8c2 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -10,7 +10,7 @@ #include #include -#include "dpu_io_util.h" +#include "dp_clk_util.h" #include "msm_drv.h" #define DP_LABEL "MDSS DP DISPLAY" From 787067989c31971e0fbbaf910e6c5ac0d4f41d64 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Sat, 11 Sep 2021 18:39:18 +0200 Subject: [PATCH 53/70] drm/msm/dpu: Add a function to retrieve the current CTL status Add a function that returns whether the requested CTL is active or not: this will be used in a later commit to fix command mode panel issues. Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20210911163919.47173-1-angelogioacchino.delregno@somainline.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 6 ++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index 02da9ecf71f11..3584f5ee6bb33 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -92,6 +92,11 @@ static inline void dpu_hw_ctl_trigger_start(struct dpu_hw_ctl *ctx) DPU_REG_WRITE(&ctx->hw, CTL_START, 0x1); } +static inline bool dpu_hw_ctl_is_started(struct dpu_hw_ctl *ctx) +{ + return !!(DPU_REG_READ(&ctx->hw, CTL_START) & BIT(0)); +} + static inline void dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl *ctx) { trace_dpu_hw_ctl_trigger_prepare(ctx->pending_flush_mask, @@ -587,6 +592,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, ops->get_pending_flush = dpu_hw_ctl_get_pending_flush; ops->get_flush_register = dpu_hw_ctl_get_flush_register; ops->trigger_start = dpu_hw_ctl_trigger_start; + ops->is_started = dpu_hw_ctl_is_started; ops->trigger_pending = dpu_hw_ctl_trigger_pending; ops->reset = dpu_hw_ctl_reset_control; ops->wait_reset_status = dpu_hw_ctl_wait_reset_status; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h index 806c171e5df21..ac15444740225 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h @@ -61,6 +61,13 @@ struct dpu_hw_ctl_ops { */ void (*trigger_start)(struct dpu_hw_ctl *ctx); + /** + * check if the ctl is started + * @ctx : ctl path ctx pointer + * @Return: true if started, false if stopped + */ + bool (*is_started)(struct dpu_hw_ctl *ctx); + /** * kickoff prepare is in progress hw operation for sw * controlled interfaces: DSI cmd mode and WB interface From 050770cbbd26d1cc2d5f4718a4595e19cb3403d8 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Sat, 11 Sep 2021 18:39:19 +0200 Subject: [PATCH 54/70] drm/msm/dpu: Fix timeout issues on command mode panels In function dpu_encoder_phys_cmd_wait_for_commit_done we are always checking if the relative CTL is started by waiting for an interrupt to fire: it is fine to do that, but then sometimes we call this function while the CTL is up and has never been put down, but that interrupt gets raised only when the CTL gets a state change from 0 to 1 (disabled to enabled), so we're going to wait for something that will never happen on its own. Solving this while avoiding to restart the CTL is actually possible and can be done by just checking if it is already up and running when the wait_for_commit_done function is called: in this case, so, if the CTL was already running, we can say that the commit is done if the command transmission is complete (in other terms, if the interface has been flushed). Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20210911163919.47173-2-angelogioacchino.delregno@somainline.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index 56c1bd2201102..d59802b67d153 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -656,6 +656,9 @@ static int dpu_encoder_phys_cmd_wait_for_commit_done( if (!dpu_encoder_phys_cmd_is_master(phys_enc)) return 0; + if (phys_enc->hw_ctl->ops.is_started(phys_enc->hw_ctl)) + return dpu_encoder_phys_cmd_wait_for_tx_complete(phys_enc); + return _dpu_encoder_phys_cmd_wait_for_ctl_start(phys_enc); } From 4d793a02c4967ab14d4ae5e86a51ee02ed78921a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 12 Feb 2022 01:40:02 +0300 Subject: [PATCH 55/70] drm/msm/dp: fix panel bridge attachment In commit 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display enable and disable") the DP driver received a drm_bridge instance, which is always attached to the encoder as a root bridge. However it conflicts with the panel_bridge support for eDP panels. The panel bridge attaches to the encoder before the "dp" bridge (DP driver's drm_bridge instance created in msm_dp_bridge_init()) has a chance to do so. Change panel bridge attachment to come after the "dp" bridge attachment (and to use it as a previous bridge). Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display enable and disable") Cc: Kuogee Hsieh Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20220211224006.1797846-2-dmitry.baryshkov@linaro.org [db: fixed commit message according to Stephen's suggestions] Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_drm.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index d4d360d19ebad..26ef41a4c1b68 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -169,16 +169,6 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display) drm_connector_attach_encoder(connector, dp_display->encoder); - if (dp_display->panel_bridge) { - ret = drm_bridge_attach(dp_display->encoder, - dp_display->panel_bridge, NULL, - DRM_BRIDGE_ATTACH_NO_CONNECTOR); - if (ret < 0) { - DRM_ERROR("failed to attach panel bridge: %d\n", ret); - return ERR_PTR(ret); - } - } - return connector; } @@ -246,5 +236,16 @@ struct drm_bridge *msm_dp_bridge_init(struct msm_dp *dp_display, struct drm_devi return ERR_PTR(rc); } + if (dp_display->panel_bridge) { + rc = drm_bridge_attach(dp_display->encoder, + dp_display->panel_bridge, bridge, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (rc < 0) { + DRM_ERROR("failed to attach panel bridge: %d\n", rc); + drm_bridge_remove(bridge); + return ERR_PTR(rc); + } + } + return bridge; } From 9aa924688095e55a727f11228d73ce8df01d2a40 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 12 Feb 2022 01:40:03 +0300 Subject: [PATCH 56/70] drm/msm/dp: support attaching bridges to the DP encoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently DP driver will allocate panel bridge for eDP panels. This supports only the following topology: - eDP encoder ⇒ eDP panel (wrapped using panel-bridge) Simplify this code to just check if there is any next bridge in the chain (be it a panel bridge or regular bridge). Rename panel_bridge field to next_bridge accordingly. This allows one to use e.g. one of the following display topologies: - eDP encoder ⇒ ptn3460 ⇒ fixed LVDS panel - eDP encoder ⇒ ptn3460 ⇒ LVDS connector with EDID lines for panel autodetect - eDP encoder ⇒ ptn3460 ⇒ THC63LVD1024 ⇒ DPI panel. - eDP encoder ⇒ LT8912 ⇒ DSI panel Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20220211224006.1797846-3-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_display.c | 2 +- drivers/gpu/drm/msm/dp/dp_display.h | 2 +- drivers/gpu/drm/msm/dp/dp_drm.c | 4 ++-- drivers/gpu/drm/msm/dp/dp_parser.c | 31 +++++++++++++++-------------- drivers/gpu/drm/msm/dp/dp_parser.h | 2 +- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 536445bb7d452..178b774a5fbd3 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -266,7 +266,7 @@ static int dp_display_bind(struct device *dev, struct device *master, goto end; } - dp->dp_display.panel_bridge = dp->parser->panel_bridge; + dp->dp_display.next_bridge = dp->parser->next_bridge; dp->aux->drm_dev = drm; rc = dp_aux_register(dp->aux); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index e3adcd578a90d..7af2b186d2d93 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -16,7 +16,7 @@ struct msm_dp { struct drm_bridge *bridge; struct drm_connector *connector; struct drm_encoder *encoder; - struct drm_bridge *panel_bridge; + struct drm_bridge *next_bridge; bool is_connected; bool audio_enabled; bool power_on; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index 26ef41a4c1b68..80f59cf990898 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -236,9 +236,9 @@ struct drm_bridge *msm_dp_bridge_init(struct msm_dp *dp_display, struct drm_devi return ERR_PTR(rc); } - if (dp_display->panel_bridge) { + if (dp_display->next_bridge) { rc = drm_bridge_attach(dp_display->encoder, - dp_display->panel_bridge, bridge, + dp_display->next_bridge, bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (rc < 0) { DRM_ERROR("failed to attach panel bridge: %d\n", rc); diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index a7acc23f742b4..901d7967370f3 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -265,23 +265,16 @@ static int dp_parser_clock(struct dp_parser *parser) return 0; } -static int dp_parser_find_panel(struct dp_parser *parser) +static int dp_parser_find_next_bridge(struct dp_parser *parser) { struct device *dev = &parser->pdev->dev; - struct drm_panel *panel; - int rc; + struct drm_bridge *bridge; - rc = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); - if (rc) { - DRM_ERROR("failed to acquire DRM panel: %d\n", rc); - return rc; - } + bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); + if (IS_ERR(bridge)) + return PTR_ERR(bridge); - parser->panel_bridge = devm_drm_panel_bridge_add(dev, panel); - if (IS_ERR(parser->panel_bridge)) { - DRM_ERROR("failed to create panel bridge\n"); - return PTR_ERR(parser->panel_bridge); - } + parser->next_bridge = bridge; return 0; } @@ -307,10 +300,18 @@ static int dp_parser_parse(struct dp_parser *parser, int connector_type) if (rc) return rc; + /* + * Currently we support external bridges only for eDP connectors. + * + * No external bridges are expected for the DisplayPort connector, + * it is physically present in a form of a DP or USB-C connector. + */ if (connector_type == DRM_MODE_CONNECTOR_eDP) { - rc = dp_parser_find_panel(parser); - if (rc) + rc = dp_parser_find_next_bridge(parser); + if (rc) { + DRM_ERROR("DP: failed to find next bridge\n"); return rc; + } } /* Map the corresponding regulator information according to diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 3172da0894216..4cec851e38d99 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -123,7 +123,7 @@ struct dp_parser { struct dp_display_data disp_data; const struct dp_regulator_cfg *regulator_cfg; u32 max_dp_lanes; - struct drm_bridge *panel_bridge; + struct drm_bridge *next_bridge; int (*parse)(struct dp_parser *parser, int connector_type); }; From d8c2f09412ebc12a71594be66fa7248b04110afa Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 12 Feb 2022 01:40:04 +0300 Subject: [PATCH 57/70] drm/msm/dp: support finding next bridge even for DP interfaces It is possible to supply display-connector (bridge) to the DP interface, add support for parsing it too. Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20220211224006.1797846-4-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_parser.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 901d7967370f3..1056b8d5755b3 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -301,17 +301,22 @@ static int dp_parser_parse(struct dp_parser *parser, int connector_type) return rc; /* - * Currently we support external bridges only for eDP connectors. + * External bridges are mandatory for eDP interfaces: one has to + * provide at least an eDP panel (which gets wrapped into panel-bridge). * - * No external bridges are expected for the DisplayPort connector, - * it is physically present in a form of a DP or USB-C connector. + * For DisplayPort interfaces external bridges are optional, so + * silently ignore an error if one is not present (-ENODEV). */ - if (connector_type == DRM_MODE_CONNECTOR_eDP) { - rc = dp_parser_find_next_bridge(parser); - if (rc) { - DRM_ERROR("DP: failed to find next bridge\n"); + rc = dp_parser_find_next_bridge(parser); + if (rc == -ENODEV) { + if (connector_type == DRM_MODE_CONNECTOR_eDP) { + DRM_ERROR("eDP: next bridge is not present\n"); return rc; } + } else if (rc) { + if (rc != -EPROBE_DEFER) + DRM_ERROR("DP: error parsing next bridge: %d\n", rc); + return rc; } /* Map the corresponding regulator information according to From f98f915b7e0f83fd108bcf716c77f316ee27f484 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 1 Feb 2022 08:16:11 -0800 Subject: [PATCH 58/70] drm/msm/gpu: Add ctx to get_param() Prep work for next patch. Signed-off-by: Rob Clark Link: https://lore.kernel.org/r/20220201161618.778455-2-robdclark@gmail.com Reviewed-by: Emma Anholt Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 3 ++- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 3 ++- drivers/gpu/drm/msm/msm_drv.c | 3 ++- drivers/gpu/drm/msm/msm_gpu.h | 3 ++- drivers/gpu/drm/msm/msm_rd.c | 6 ++++-- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index f33cfa4ef1c87..caa9076197deb 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -227,7 +227,8 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu, return aspace; } -int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value) +int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, + uint32_t param, uint64_t *value) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index cffabe7d33c19..432590036b318 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -279,7 +279,8 @@ static inline int adreno_is_a650_family(struct adreno_gpu *gpu) adreno_is_a660_family(gpu); } -int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value); +int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, + uint32_t param, uint64_t *value); const struct firmware *adreno_request_fw(struct adreno_gpu *adreno_gpu, const char *fwname); struct drm_gem_object *adreno_fw_create_bo(struct msm_gpu *gpu, diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 9572fabe23455..2038973022b04 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -609,7 +609,8 @@ static int msm_ioctl_get_param(struct drm_device *dev, void *data, if (!gpu) return -ENXIO; - return gpu->funcs->get_param(gpu, args->param, &args->value); + return gpu->funcs->get_param(gpu, file->driver_priv, + args->param, &args->value); } static int msm_ioctl_gem_new(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 92aa1e9196c64..ba84072313400 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -42,7 +42,8 @@ struct msm_gpu_config { * + z180_gpu */ struct msm_gpu_funcs { - int (*get_param)(struct msm_gpu *gpu, uint32_t param, uint64_t *value); + int (*get_param)(struct msm_gpu *gpu, struct msm_file_private *ctx, + uint32_t param, uint64_t *value); int (*hw_init)(struct msm_gpu *gpu); int (*pm_suspend)(struct msm_gpu *gpu); int (*pm_resume)(struct msm_gpu *gpu); diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c index 7e4d6460719eb..9d835331f2149 100644 --- a/drivers/gpu/drm/msm/msm_rd.c +++ b/drivers/gpu/drm/msm/msm_rd.c @@ -197,13 +197,15 @@ static int rd_open(struct inode *inode, struct file *file) /* the parsing tools need to know gpu-id to know which * register database to load. + * + * Note: These particular params do not require a context */ - gpu->funcs->get_param(gpu, MSM_PARAM_GPU_ID, &val); + gpu->funcs->get_param(gpu, NULL, MSM_PARAM_GPU_ID, &val); gpu_id = val; rd_write_section(rd, RD_GPU_ID, &gpu_id, sizeof(gpu_id)); - gpu->funcs->get_param(gpu, MSM_PARAM_CHIP_ID, &val); + gpu->funcs->get_param(gpu, NULL, MSM_PARAM_CHIP_ID, &val); rd_write_section(rd, RD_CHIP_ID, &val, sizeof(val)); out: From bc2112583a0b473f5c4ba87c00da84abd5d0b3fd Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 1 Feb 2022 08:16:12 -0800 Subject: [PATCH 59/70] drm/msm/gpu: Track global faults per address-space Other processes don't need to know about faults that they are isolated from by virtue of address space isolation. They are only interested in whether some of their state might have been corrupted. But to be safe, also track unattributed faults. This case should really never happen unless there is a kernel bug (and that would never happen, right?) v2: Instead of adding a new param, just change the behavior of the existing param to match what userspace actually wants [anholt] Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/5934 Signed-off-by: Rob Clark Link: https://lore.kernel.org/r/20220201161618.778455-3-robdclark@gmail.com Reviewed-by: Emma Anholt Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +- drivers/gpu/drm/msm/msm_gem.h | 3 +++ drivers/gpu/drm/msm/msm_gpu.c | 8 +++++++- drivers/gpu/drm/msm/msm_gpu.h | 5 ++++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index caa9076197deb..58dfb23cf2afa 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -269,7 +269,7 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, *value = 0; return 0; case MSM_PARAM_FAULTS: - *value = gpu->global_faults; + *value = gpu->global_faults + ctx->aspace->faults; return 0; case MSM_PARAM_SUSPENDS: *value = gpu->suspend_count; diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 54ca0817d8071..af612add52647 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -35,6 +35,9 @@ struct msm_gem_address_space { * will be non-NULL: */ struct pid *pid; + + /* @faults: the number of GPU hangs associated with this address space */ + int faults; }; struct msm_gem_vma { diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 998e705c15efa..173ebd449f2fd 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -370,8 +370,8 @@ static void recover_worker(struct kthread_work *work) struct task_struct *task; /* Increment the fault counts */ - gpu->global_faults++; submit->queue->faults++; + submit->aspace->faults++; task = get_pid_task(submit->pid, PIDTYPE_PID); if (task) { @@ -389,6 +389,12 @@ static void recover_worker(struct kthread_work *work) } else { msm_rd_dump_submit(priv->hangrd, submit, NULL); } + } else { + /* + * We couldn't attribute this fault to any particular context, + * so increment the global fault count instead. + */ + gpu->global_faults++; } /* Record the crash state */ diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index ba84072313400..c99627fc99ddb 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -200,7 +200,10 @@ struct msm_gpu { /* does gpu need hw_init? */ bool needs_hw_init; - /* number of GPU hangs (for all contexts) */ + /** + * global_faults: number of GPU hangs not attributed to a particular + * address space + */ int global_faults; void __iomem *mmio; From 05ae15e762718d4c76fa34b2a62072940db1283c Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 14 Feb 2022 16:37:38 +0100 Subject: [PATCH 60/70] drm/msm/dsi: Allow to specify dsi config as pdata Config autodetect based on DSI controller version is quite limited since several qcom SoCs can integrate a DSI controller with the same version, but with different config (io_offset, supplies, etc). This change allows to specify dsi config via device data pointer. config autodetect is still used in case data pointer is NULL. Signed-off-by: Loic Poulain Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/474089/ Link: https://lore.kernel.org/r/1644853060-12222-1-git-send-email-loic.poulain@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi.c | 2 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 0fe02529b5e7a..e61a8eec53191 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -175,7 +175,7 @@ static int dsi_dev_remove(struct platform_device *pdev) } static const struct of_device_id dt_match[] = { - { .compatible = "qcom,mdss-dsi-ctrl" }, + { .compatible = "qcom,mdss-dsi-ctrl", .data = NULL /* autodetect cfg */ }, {} }; diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index be474dcdc9bcd..d51e70fab93db 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -212,6 +212,10 @@ static const struct msm_dsi_cfg_handler *dsi_get_config( int ret; u32 major = 0, minor = 0; + cfg_hnd = device_get_match_data(dev); + if (cfg_hnd) + return cfg_hnd; + ahb_clk = msm_clk_get(msm_host->pdev, "iface"); if (IS_ERR(ahb_clk)) { pr_err("%s: cannot get interface clock\n", __func__); From ee1f09678f14a037b6bb4d482e0fb6b2016360fb Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 14 Feb 2022 16:37:39 +0100 Subject: [PATCH 61/70] drm/msm/dsi: Add support for qcm2290 dsi controller QCM2290 MDSS includes a Qualcomm DSI controller v2.4.1. Since this controller version is not SoC specific, and already assigned to sc7180 for auto configuration, we rely on DSI block specific compatible string "qcom,dsi-ctrl-6g-qcm2290", and use the device's data to point to the right dsi config handler. Signed-off-by: Loic Poulain Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/474088/ Link: https://lore.kernel.org/r/1644853060-12222-2-git-send-email-loic.poulain@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi.c | 2 ++ drivers/gpu/drm/msm/dsi/dsi_cfg.c | 23 +++++++++++++++++++++++ drivers/gpu/drm/msm/dsi/dsi_cfg.h | 3 +++ 3 files changed, 28 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index e61a8eec53191..c12e66aa42a3b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -4,6 +4,7 @@ */ #include "dsi.h" +#include "dsi_cfg.h" struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi) { @@ -176,6 +177,7 @@ static int dsi_dev_remove(struct platform_device *pdev) static const struct of_device_id dt_match[] = { { .compatible = "qcom,mdss-dsi-ctrl", .data = NULL /* autodetect cfg */ }, + { .compatible = "qcom,dsi-ctrl-6g-qcm2290", .data = &qcm2290_dsi_cfg_handler }, {} }; diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 96bbc8b6d0092..2c23324a2296b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -213,6 +213,24 @@ static const struct msm_dsi_config sc7280_dsi_cfg = { .num_dsi = 1, }; +static const char * const dsi_qcm2290_bus_clk_names[] = { + "iface", "bus", +}; + +static const struct msm_dsi_config qcm2290_dsi_cfg = { + .io_offset = DSI_6G_REG_SHIFT, + .reg_cfg = { + .num = 1, + .regs = { + {"vdda", 21800, 4 }, /* 1.2 V */ + }, + }, + .bus_clk_names = dsi_qcm2290_bus_clk_names, + .num_bus_clks = ARRAY_SIZE(dsi_qcm2290_bus_clk_names), + .io_start = { 0x5e94000 }, + .num_dsi = 1, +}; + static const struct msm_dsi_host_cfg_ops msm_dsi_v2_host_ops = { .link_clk_set_rate = dsi_link_clk_set_rate_v2, .link_clk_enable = dsi_link_clk_enable_v2, @@ -300,3 +318,8 @@ const struct msm_dsi_cfg_handler *msm_dsi_cfg_get(u32 major, u32 minor) return cfg_hnd; } +/* Non autodetect configs */ +const struct msm_dsi_cfg_handler qcm2290_dsi_cfg_handler = { + .cfg = &qcm2290_dsi_cfg, + .ops = &msm_dsi_6g_v2_host_ops, +}; diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h index 41e99a9fb5de5..fe54a999968bd 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h @@ -60,5 +60,8 @@ struct msm_dsi_cfg_handler { const struct msm_dsi_cfg_handler *msm_dsi_cfg_get(u32 major, u32 minor); +/* Non autodetect configs */ +extern const struct msm_dsi_cfg_handler qcm2290_dsi_cfg_handler; + #endif /* __MSM_DSI_CFG_H__ */ From 201d41745ea9173e0463a164af493c2c49c29e80 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 14 Feb 2022 16:37:40 +0100 Subject: [PATCH 62/70] dt-bindings: msm/dsi: Add qcm2290 dsi controller binding Add DSI block specific qcm2290 compatible string as valid Qualcomm DSI controller. Signed-off-by: Loic Poulain Acked-by: Rob Herring Patchwork: https://patchwork.freedesktop.org/patch/474090/ Link: https://lore.kernel.org/r/1644853060-12222-3-git-send-email-loic.poulain@linaro.org Signed-off-by: Dmitry Baryshkov --- .../devicetree/bindings/display/msm/dsi-controller-main.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml index 35426fde86106..7095ec3c890da 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml @@ -14,8 +14,9 @@ allOf: properties: compatible: - items: - - const: qcom,mdss-dsi-ctrl + enum: + - qcom,mdss-dsi-ctrl + - qcom,dsi-ctrl-6g-qcm2290 reg: maxItems: 1 From 5334087ee7438fa8a76cf1866b4811f57a01a7e9 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 14 Feb 2022 16:29:06 +0100 Subject: [PATCH 63/70] drm/msm: add support for QCM2290 MDSS Add compatibility for QCM2290 display subsystem, including required entries in DPU hw catalog. Signed-off-by: Loic Poulain Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/474087/ Link: https://lore.kernel.org/r/1644852547-10067-1-git-send-email-loic.poulain@linaro.org Signed-off-by: Dmitry Baryshkov --- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 148 ++++++++++++++++++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 + drivers/gpu/drm/msm/msm_drv.c | 1 + 4 files changed, 151 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index aa4d20762ccb8..ddd13c93ef9fc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -28,6 +28,8 @@ #define VIG_SM8250_MASK \ (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3LITE)) +#define VIG_QCM2290_MASK (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL)) + #define DMA_MSM8998_MASK \ (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\ BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\ @@ -336,6 +338,17 @@ static const struct dpu_mdp_cfg msm8998_mdp[] = { }, }; +static const struct dpu_caps qcm2290_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0x4, + .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, + .ubwc_version = DPU_HW_UBWC_VER_20, + .has_dim_layer = true, + .has_idle_pc = true, + .max_linewidth = 2160, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, +}; + static const struct dpu_mdp_cfg sdm845_mdp[] = { { .name = "top_0", .id = MDP_TOP, @@ -446,6 +459,19 @@ static const struct dpu_mdp_cfg sc7280_mdp[] = { }, }; +static const struct dpu_mdp_cfg qcm2290_mdp[] = { + { + .name = "top_0", .id = MDP_TOP, + .base = 0x0, .len = 0x494, + .features = 0, + .highest_bank_bit = 0x2, + .clk_ctrls[DPU_CLK_CTRL_VIG0] = { + .reg_off = 0x2AC, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA0] = { + .reg_off = 0x2AC, .bit_off = 8}, + }, +}; + /************************************************************* * CTL sub blocks config *************************************************************/ @@ -602,6 +628,15 @@ static const struct dpu_ctl_cfg sc7280_ctl[] = { }, }; +static const struct dpu_ctl_cfg qcm2290_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x1000, .len = 0x1dc, + .features = BIT(DPU_CTL_ACTIVE_CFG), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, +}; + /************************************************************* * SSPP sub blocks config *************************************************************/ @@ -766,6 +801,30 @@ static const struct dpu_sspp_cfg sc7280_sspp[] = { sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), }; + +#define _VIG_SBLK_NOSCALE(num, sdma_pri) \ + { \ + .maxdwnscale = SSPP_UNITY_SCALE, \ + .maxupscale = SSPP_UNITY_SCALE, \ + .smart_dma_priority = sdma_pri, \ + .src_blk = {.name = STRCAT("sspp_src_", num), \ + .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \ + .format_list = plane_formats_yuv, \ + .num_formats = ARRAY_SIZE(plane_formats_yuv), \ + .virt_format_list = plane_formats, \ + .virt_num_formats = ARRAY_SIZE(plane_formats), \ + } + +static const struct dpu_sspp_sub_blks qcm2290_vig_sblk_0 = _VIG_SBLK_NOSCALE("0", 2); +static const struct dpu_sspp_sub_blks qcm2290_dma_sblk_0 = _DMA_SBLK("8", 1); + +static const struct dpu_sspp_cfg qcm2290_sspp[] = { + SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_QCM2290_MASK, + qcm2290_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), + SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK, + qcm2290_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), +}; + /************************************************************* * MIXER sub blocks config *************************************************************/ @@ -876,6 +935,21 @@ static const struct dpu_lm_cfg sc7280_lm[] = { &sc7180_lm_sblk, PINGPONG_3, LM_2, 0), }; +/* QCM2290 */ + +static const struct dpu_lm_sub_blks qcm2290_lm_sblk = { + .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .maxblendstages = 4, /* excluding base layer */ + .blendstage_base = { /* offsets relative to mixer base */ + 0x20, 0x38, 0x50, 0x68 + }, +}; + +static const struct dpu_lm_cfg qcm2290_lm[] = { + LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK, + &qcm2290_lm_sblk, PINGPONG_0, 0, DSPP_0), +}; + /************************************************************* * DSPP sub blocks config *************************************************************/ @@ -927,6 +1001,11 @@ static const struct dpu_dspp_cfg sm8150_dspp[] = { &sm8150_dspp_sblk), }; +static const struct dpu_dspp_cfg qcm2290_dspp[] = { + DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK, + &sm8150_dspp_sblk), +}; + /************************************************************* * PINGPONG sub blocks config *************************************************************/ @@ -1009,6 +1088,12 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = { -1), }; +static struct dpu_pingpong_cfg qcm2290_pp[] = { + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), +}; + /************************************************************* * MERGE_3D sub blocks config *************************************************************/ @@ -1089,6 +1174,11 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 22, 23), }; +static const struct dpu_intf_cfg qcm2290_intf[] = { + INTF_BLK("intf_0", INTF_0, 0x00000, INTF_NONE, 0, 0, 0, 0, 0, 0), + INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27), +}; + /************************************************************* * VBIF sub blocks config *************************************************************/ @@ -1234,6 +1324,10 @@ static const struct dpu_qos_lut_entry sc8180x_qos_linear[] = { {.fl = 4, .lut = 0x0000000000000357 }, }; +static const struct dpu_qos_lut_entry qcm2290_qos_linear[] = { + {.fl = 0, .lut = 0x0011222222335777}, +}; + static const struct dpu_qos_lut_entry sdm845_qos_macrotile[] = { {.fl = 10, .lut = 0x344556677}, {.fl = 11, .lut = 0x3344556677}, @@ -1476,6 +1570,27 @@ static const struct dpu_perf_cfg sc7280_perf_data = { .bw_inefficiency_factor = 120, }; +static const struct dpu_perf_cfg qcm2290_perf_data = { + .max_bw_low = 2700000, + .max_bw_high = 2700000, + .min_core_ib = 1300000, + .min_llcc_ib = 0, + .min_dram_ib = 1600000, + .min_prefill_lines = 24, + .danger_lut_tbl = {0xff, 0x0, 0x0}, + .safe_lut_tbl = {0xfff0, 0x0, 0x0}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(qcm2290_qos_linear), + .entries = qcm2290_qos_linear + }, + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; /************************************************************* * Hardware catalog init *************************************************************/ @@ -1688,6 +1803,38 @@ static void sc7280_cfg_init(struct dpu_mdss_cfg *dpu_cfg) }; } + +/* + * qcm2290_cfg_init(): populate qcm2290 dpu sub-blocks reg offsets + * and instance counts. + */ +static void qcm2290_cfg_init(struct dpu_mdss_cfg *dpu_cfg) +{ + *dpu_cfg = (struct dpu_mdss_cfg){ + .caps = &qcm2290_dpu_caps, + .mdp_count = ARRAY_SIZE(qcm2290_mdp), + .mdp = qcm2290_mdp, + .ctl_count = ARRAY_SIZE(qcm2290_ctl), + .ctl = qcm2290_ctl, + .sspp_count = ARRAY_SIZE(qcm2290_sspp), + .sspp = qcm2290_sspp, + .mixer_count = ARRAY_SIZE(qcm2290_lm), + .mixer = qcm2290_lm, + .dspp_count = ARRAY_SIZE(qcm2290_dspp), + .dspp = qcm2290_dspp, + .pingpong_count = ARRAY_SIZE(qcm2290_pp), + .pingpong = qcm2290_pp, + .intf_count = ARRAY_SIZE(qcm2290_intf), + .intf = qcm2290_intf, + .vbif_count = ARRAY_SIZE(sdm845_vbif), + .vbif = sdm845_vbif, + .reg_dma_count = 1, + .dma_cfg = sdm845_regdma, + .perf = qcm2290_perf_data, + .mdss_irqs = IRQ_SC7180_MASK, + }; +} + static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = { { .hw_rev = DPU_HW_VER_300, .cfg_init = msm8998_cfg_init}, { .hw_rev = DPU_HW_VER_301, .cfg_init = msm8998_cfg_init}, @@ -1698,6 +1845,7 @@ static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = { { .hw_rev = DPU_HW_VER_510, .cfg_init = sc8180x_cfg_init}, { .hw_rev = DPU_HW_VER_600, .cfg_init = sm8250_cfg_init}, { .hw_rev = DPU_HW_VER_620, .cfg_init = sc7180_cfg_init}, + { .hw_rev = DPU_HW_VER_650, .cfg_init = qcm2290_cfg_init}, { .hw_rev = DPU_HW_VER_720, .cfg_init = sc7280_cfg_init}, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 2a5e3956ed4ad..b85b24bd3f53e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -42,6 +42,7 @@ #define DPU_HW_VER_510 DPU_HW_VER(5, 1, 1) /* sc8180 */ #define DPU_HW_VER_600 DPU_HW_VER(6, 0, 0) /* sm8250 */ #define DPU_HW_VER_620 DPU_HW_VER(6, 2, 0) /* sc7180 v1.0 */ +#define DPU_HW_VER_650 DPU_HW_VER(6, 5, 0) /* qcm2290|sm4125 */ #define DPU_HW_VER_720 DPU_HW_VER(7, 2, 0) /* sc7280 */ #define IS_MSM8996_TARGET(rev) IS_DPU_MAJOR_MINOR_SAME((rev), DPU_HW_VER_170) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index d4c023b9228c4..252ce02aa661d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1329,6 +1329,7 @@ static const struct dev_pm_ops dpu_pm_ops = { const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,msm8998-dpu", }, + { .compatible = "qcom,qcm2290-dpu", }, { .compatible = "qcom,sdm845-dpu", }, { .compatible = "qcom,sc7180-dpu", }, { .compatible = "qcom,sc7280-dpu", }, diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 5d153ec94fe97..8a1da45722907 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1436,6 +1436,7 @@ static const struct of_device_id dt_match[] = { { .compatible = "qcom,mdp4", .data = (void *)KMS_MDP4 }, { .compatible = "qcom,mdss", .data = (void *)KMS_MDP5 }, { .compatible = "qcom,msm8998-mdss", .data = (void *)KMS_DPU }, + { .compatible = "qcom,qcm2290-mdss", .data = (void *)KMS_DPU }, { .compatible = "qcom,sdm845-mdss", .data = (void *)KMS_DPU }, { .compatible = "qcom,sc7180-mdss", .data = (void *)KMS_DPU }, { .compatible = "qcom,sc7280-mdss", .data = (void *)KMS_DPU }, From 164f69d9d45a605574c0d0f05a21a6faf6f33657 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 14 Feb 2022 16:29:07 +0100 Subject: [PATCH 64/70] dt-bindings: msm: disp: add yaml schemas for QCM2290 DPU bindings QCM2290 MSM Mobile Display Subsystem (MDSS) encapsulates sub-blocks like DPU display controller, DSI etc. Add YAML schema for DPU device tree bindings Signed-off-by: Loic Poulain Reviewed-by: Rob Herring Patchwork: https://patchwork.freedesktop.org/patch/474091/ Link: https://lore.kernel.org/r/1644852547-10067-2-git-send-email-loic.poulain@linaro.org Signed-off-by: Dmitry Baryshkov --- .../bindings/display/msm/dpu-qcm2290.yaml | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml diff --git a/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml b/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml new file mode 100644 index 0000000000000..8766b13f0c46a --- /dev/null +++ b/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml @@ -0,0 +1,214 @@ +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/msm/dpu-qcm2290.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Display DPU dt properties for QCM2290 target + +maintainers: + - Loic Poulain + +description: | + Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates + sub-blocks like DPU display controller and DSI. Device tree bindings of MDSS + and DPU are mentioned for QCM2290 target. + +properties: + compatible: + items: + - const: qcom,qcm2290-mdss + + reg: + maxItems: 1 + + reg-names: + const: mdss + + power-domains: + maxItems: 1 + + clocks: + items: + - description: Display AHB clock from gcc + - description: Display AXI clock + - description: Display core clock + + clock-names: + items: + - const: iface + - const: bus + - const: core + + interrupts: + maxItems: 1 + + interrupt-controller: true + + "#address-cells": true + + "#size-cells": true + + "#interrupt-cells": + const: 1 + + iommus: + items: + - description: Phandle to apps_smmu node with SID mask for Hard-Fail port0 + - description: Phandle to apps_smmu node with SID mask for Hard-Fail port1 + + ranges: true + + interconnects: + items: + - description: Interconnect path specifying the port ids for data bus + + interconnect-names: + const: mdp0-mem + +patternProperties: + "^display-controller@[0-9a-f]+$": + type: object + description: Node containing the properties of DPU. + + properties: + compatible: + items: + - const: qcom,qcm2290-dpu + + reg: + items: + - description: Address offset and size for mdp register set + - description: Address offset and size for vbif register set + + reg-names: + items: + - const: mdp + - const: vbif + + clocks: + items: + - description: Display AXI clock from gcc + - description: Display AHB clock from dispcc + - description: Display core clock from dispcc + - description: Display lut clock from dispcc + - description: Display vsync clock from dispcc + + clock-names: + items: + - const: bus + - const: iface + - const: core + - const: lut + - const: vsync + + interrupts: + maxItems: 1 + + power-domains: + maxItems: 1 + + operating-points-v2: true + + ports: + $ref: /schemas/graph.yaml#/properties/ports + description: | + Contains the list of output ports from DPU device. These ports + connect to interfaces that are external to the DPU hardware, + such as DSI. Each output port contains an endpoint that + describes how it is connected to an external interface. + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: DPU_INTF1 (DSI1) + + required: + - port@0 + + required: + - compatible + - reg + - reg-names + - clocks + - interrupts + - power-domains + - operating-points-v2 + - ports + +required: + - compatible + - reg + - reg-names + - power-domains + - clocks + - interrupts + - interrupt-controller + - iommus + - ranges + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + + mdss: mdss@5e00000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "qcom,qcm2290-mdss", "qcom,mdss"; + reg = <0x05e00000 0x1000>; + reg-names = "mdss"; + power-domains = <&dispcc MDSS_GDSC>; + clocks = <&gcc GCC_DISP_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", "bus", "core"; + + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + interconnects = <&mmrt_virt MASTER_MDP0 &bimc SLAVE_EBI1>; + interconnect-names = "mdp0-mem"; + + iommus = <&apps_smmu 0x420 0x2>, + <&apps_smmu 0x421 0x0>; + ranges; + + mdss_mdp: mdp@5e01000 { + compatible = "qcom,qcm2290-dpu"; + reg = <0x05e01000 0x8f000>, + <0x05eb0000 0x2008>; + reg-names = "mdp", "vbif"; + + clocks = <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "bus", "iface", "core", "lut", "vsync"; + + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmpd QCM2290_VDDCX>; + + interrupt-parent = <&mdss>; + interrupts = <0 IRQ_TYPE_NONE>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + }; + }; +... From 6452cbd6f04cd57f7e365cc5bc65be0a69e8e40b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 22 Feb 2022 06:19:48 +0300 Subject: [PATCH 65/70] drm/msm/dpu: wire up MSM8998's DSPP blocks The commit adding msm8998 support didn't added msm8998's DSPP blocks configuration, but did not use them in msm8998_cfg_init(). Wire them up to be used for display post processing. Reported-by: kernel test robot Fixes: 94391a14fc27 ("drm/msm/dpu1: Add MSM8998 to hw catalog") Cc: AngeloGioacchino Del Regno Cc: Jami Kettunen Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/475544/ Link: https://lore.kernel.org/r/20220222031948.228727-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index ddd13c93ef9fc..a4fe77cddfea0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -1611,6 +1611,8 @@ static void msm8998_cfg_init(struct dpu_mdss_cfg *dpu_cfg) .sspp = msm8998_sspp, .mixer_count = ARRAY_SIZE(msm8998_lm), .mixer = msm8998_lm, + .dspp_count = ARRAY_SIZE(msm8998_dspp), + .dspp = msm8998_dspp, .pingpong_count = ARRAY_SIZE(sdm845_pp), .pingpong = sdm845_pp, .intf_count = ARRAY_SIZE(msm8998_intf), From 9e4dde28e9cd34ee13a6b7247f0857fb49fd3f19 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 23 Feb 2022 11:11:08 -0800 Subject: [PATCH 66/70] drm/msm: Avoid dirtyfb stalls on video mode displays (v2) Someone on IRC once asked an innocent enough sounding question: Why with xf86-video-modesetting is es2gears limited at 120fps. So I broke out the perfetto tracing mesa MR and took a look. It turns out the problem was drm_atomic_helper_dirtyfb(), which would end up waiting for vblank.. es2gears would rapidly push two frames to Xorg, which would blit them to screen and in idle hook (I assume) call the DIRTYFB ioctl. Which in turn would do an atomic update to flush the dirty rects, which would stall until the next vblank. And then the whole process would repeat. But this is a bit silly, we only need dirtyfb for command mode DSI panels. So track in plane state whether dirtyfb is required, and track in the fb how many attached planes require dirtyfb so that we can skip it when not required. (Note, mdp4 does not actually have cmd mode support.) Signed-off-by: Rob Clark Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220223191118.881321-1-robdclark@gmail.com Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 20 ++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 5 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 3 ++ drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c | 19 ++++++++-- drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 8 +++++ drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h | 5 +++ drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 21 +++++++++-- drivers/gpu/drm/msm/msm_atomic.c | 15 -------- drivers/gpu/drm/msm/msm_drv.h | 6 ++-- drivers/gpu/drm/msm/msm_fb.c | 41 ++++++++++++++++++---- 10 files changed, 110 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 662b7bc9c219c..7763558ef566b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1046,6 +1046,20 @@ struct plane_state { u32 pipe_id; }; +static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate) +{ + struct drm_crtc *crtc = cstate->crtc; + struct drm_encoder *encoder; + + drm_for_each_encoder_mask (encoder, crtc->dev, cstate->encoder_mask) { + if (dpu_encoder_get_intf_mode(encoder) == INTF_MODE_CMD) { + return true; + } + } + + return false; +} + static int dpu_crtc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) { @@ -1066,6 +1080,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, const struct drm_plane_state *pipe_staged[SSPP_MAX]; int left_zpos_cnt = 0, right_zpos_cnt = 0; struct drm_rect crtc_rect = { 0 }; + bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state); pstates = kzalloc(sizeof(*pstates) * DPU_STAGE_MAX * 4, GFP_KERNEL); @@ -1097,6 +1112,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, /* get plane state for all drm planes associated with crtc state */ drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) { + struct dpu_plane_state *dpu_pstate = to_dpu_plane_state(pstate); struct drm_rect dst, clip = crtc_rect; if (IS_ERR_OR_NULL(pstate)) { @@ -1108,11 +1124,13 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, if (cnt >= DPU_STAGE_MAX * 4) continue; - pstates[cnt].dpu_pstate = to_dpu_plane_state(pstate); + pstates[cnt].dpu_pstate = dpu_pstate; pstates[cnt].drm_pstate = pstate; pstates[cnt].stage = pstate->normalized_zpos; pstates[cnt].pipe_id = dpu_plane_pipe(plane); + dpu_pstate->needs_dirtyfb = needs_dirtyfb; + if (pipe_staged[pstates[cnt].pipe_id]) { multirect_plane[multirect_count].r0 = pipe_staged[pstates[cnt].pipe_id]; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index ca75089c9d611..6565682fe2273 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -902,7 +902,7 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane, if (pstate->aspace) { ret = msm_framebuffer_prepare(new_state->fb, - pstate->aspace); + pstate->aspace, pstate->needs_dirtyfb); if (ret) { DPU_ERROR("failed to prepare framebuffer\n"); return ret; @@ -933,7 +933,8 @@ static void dpu_plane_cleanup_fb(struct drm_plane *plane, DPU_DEBUG_PLANE(pdpu, "FB[%u]\n", old_state->fb->base.id); - msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace); + msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace, + old_pstate->needs_dirtyfb); } static bool dpu_plane_validate_src(struct drm_rect *src, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h index 9d51dad5c6a52..50781e2d35772 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h @@ -25,6 +25,7 @@ * @pending: whether the current update is still pending * @plane_fetch_bw: calculated BW per plane * @plane_clk: calculated clk per plane + * @needs_dirtyfb: whether attached CRTC needs pixel data explicitly flushed */ struct dpu_plane_state { struct drm_plane_state base; @@ -37,6 +38,8 @@ struct dpu_plane_state { u64 plane_fetch_bw; u64 plane_clk; + + bool needs_dirtyfb; }; /** diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c index 49bdabea8ed59..3e20f72d75efd 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "mdp4_kms.h" @@ -90,6 +91,20 @@ static const struct drm_plane_funcs mdp4_plane_funcs = { .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, }; +static int mdp4_plane_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct msm_drm_private *priv = plane->dev->dev_private; + struct msm_kms *kms = priv->kms; + + if (!new_state->fb) + return 0; + + drm_gem_plane_helper_prepare_fb(plane, new_state); + + return msm_framebuffer_prepare(new_state->fb, kms->aspace, false); +} + static void mdp4_plane_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state) { @@ -102,7 +117,7 @@ static void mdp4_plane_cleanup_fb(struct drm_plane *plane, return; DBG("%s: cleanup: FB[%u]", mdp4_plane->name, fb->base.id); - msm_framebuffer_cleanup(fb, kms->aspace); + msm_framebuffer_cleanup(fb, kms->aspace, false); } @@ -130,7 +145,7 @@ static void mdp4_plane_atomic_update(struct drm_plane *plane, } static const struct drm_plane_helper_funcs mdp4_plane_helper_funcs = { - .prepare_fb = msm_atomic_prepare_fb, + .prepare_fb = mdp4_plane_prepare_fb, .cleanup_fb = mdp4_plane_cleanup_fb, .atomic_check = mdp4_plane_atomic_check, .atomic_update = mdp4_plane_atomic_update, diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c index bb7d066618e64..b966cd69f99dd 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -690,6 +690,8 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, { struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc_state); + struct mdp5_interface *intf = mdp5_cstate->pipeline.intf; struct mdp5_kms *mdp5_kms = get_kms(crtc); struct drm_plane *plane; struct drm_device *dev = crtc->dev; @@ -706,12 +708,18 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, DBG("%s: check", crtc->name); drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) { + struct mdp5_plane_state *mdp5_pstate = + to_mdp5_plane_state(pstate); + if (!pstate->visible) continue; pstates[cnt].plane = plane; pstates[cnt].state = to_mdp5_plane_state(pstate); + mdp5_pstate->needs_dirtyfb = + intf->mode == MDP5_INTF_DSI_MODE_COMMAND; + /* * if any plane on this crtc uses 2 hwpipes, then we need * the crtc to have a right hwmixer. diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h index ac269a6802df2..29bf11f086011 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h @@ -100,6 +100,11 @@ struct mdp5_plane_state { /* assigned by crtc blender */ enum mdp_mixer_stage_id stage; + + /* whether attached CRTC needs pixel data explicitly flushed to + * display (ex. DSI command mode display) + */ + bool needs_dirtyfb; }; #define to_mdp5_plane_state(x) \ container_of(x, struct mdp5_plane_state, base) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c index c6b69afcbac89..b176338ab59b8 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "mdp5_kms.h" @@ -140,18 +141,34 @@ static const struct drm_plane_funcs mdp5_plane_funcs = { .atomic_print_state = mdp5_plane_atomic_print_state, }; +static int mdp5_plane_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct msm_drm_private *priv = plane->dev->dev_private; + struct msm_kms *kms = priv->kms; + bool needs_dirtyfb = to_mdp5_plane_state(new_state)->needs_dirtyfb; + + if (!new_state->fb) + return 0; + + drm_gem_plane_helper_prepare_fb(plane, new_state); + + return msm_framebuffer_prepare(new_state->fb, kms->aspace, needs_dirtyfb); +} + static void mdp5_plane_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state) { struct mdp5_kms *mdp5_kms = get_kms(plane); struct msm_kms *kms = &mdp5_kms->base.base; struct drm_framebuffer *fb = old_state->fb; + bool needed_dirtyfb = to_mdp5_plane_state(old_state)->needs_dirtyfb; if (!fb) return; DBG("%s: cleanup: FB[%u]", plane->name, fb->base.id); - msm_framebuffer_cleanup(fb, kms->aspace); + msm_framebuffer_cleanup(fb, kms->aspace, needed_dirtyfb); } static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state, @@ -437,7 +454,7 @@ static void mdp5_plane_atomic_async_update(struct drm_plane *plane, } static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = { - .prepare_fb = msm_atomic_prepare_fb, + .prepare_fb = mdp5_plane_prepare_fb, .cleanup_fb = mdp5_plane_cleanup_fb, .atomic_check = mdp5_plane_atomic_check, .atomic_update = mdp5_plane_atomic_update, diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 27c9ae563f2f6..1686fbb611fd7 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -5,7 +5,6 @@ */ #include -#include #include #include "msm_atomic_trace.h" @@ -13,20 +12,6 @@ #include "msm_gem.h" #include "msm_kms.h" -int msm_atomic_prepare_fb(struct drm_plane *plane, - struct drm_plane_state *new_state) -{ - struct msm_drm_private *priv = plane->dev->dev_private; - struct msm_kms *kms = priv->kms; - - if (!new_state->fb) - return 0; - - drm_gem_plane_helper_prepare_fb(plane, new_state); - - return msm_framebuffer_prepare(new_state->fb, kms->aspace); -} - /* * Helpers to control vblanks while we flush.. basically just to ensure * that vblank accounting is switched on, so we get valid seqn/timestamp diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 57b0cd6f917e8..9f68aa685ed78 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -239,8 +239,6 @@ struct msm_format { struct msm_pending_timer; -int msm_atomic_prepare_fb(struct drm_plane *plane, - struct drm_plane_state *new_state); int msm_atomic_init_pending_timer(struct msm_pending_timer *timer, struct msm_kms *kms, int crtc_idx); void msm_atomic_destroy_pending_timer(struct msm_pending_timer *timer); @@ -299,9 +297,9 @@ int msm_gem_prime_pin(struct drm_gem_object *obj); void msm_gem_prime_unpin(struct drm_gem_object *obj); int msm_framebuffer_prepare(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace); + struct msm_gem_address_space *aspace, bool needs_dirtyfb); void msm_framebuffer_cleanup(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace); + struct msm_gem_address_space *aspace, bool needed_dirtyfb); uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, struct msm_gem_address_space *aspace, int plane); struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane); diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 4d34df5354e07..96b379a08327c 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -18,16 +18,36 @@ struct msm_framebuffer { struct drm_framebuffer base; const struct msm_format *format; + + /* Count of # of attached planes which need dirtyfb: */ + refcount_t dirtyfb; }; #define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base) static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos); +static int msm_framebuffer_dirtyfb(struct drm_framebuffer *fb, + struct drm_file *file_priv, unsigned int flags, + unsigned int color, struct drm_clip_rect *clips, + unsigned int num_clips) +{ + struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); + + /* If this fb is not used on any display requiring pixel data to be + * flushed, then skip dirtyfb + */ + if (refcount_read(&msm_fb->dirtyfb) == 0) + return 0; + + return drm_atomic_helper_dirtyfb(fb, file_priv, flags, color, + clips, num_clips); +} + static const struct drm_framebuffer_funcs msm_framebuffer_funcs = { .create_handle = drm_gem_fb_create_handle, .destroy = drm_gem_fb_destroy, - .dirty = drm_atomic_helper_dirtyfb, + .dirty = msm_framebuffer_dirtyfb, }; #ifdef CONFIG_DEBUG_FS @@ -48,17 +68,19 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) } #endif -/* prepare/pin all the fb's bo's for scanout. Note that it is not valid - * to prepare an fb more multiple different initiator 'id's. But that - * should be fine, since only the scanout (mdpN) side of things needs - * this, the gpu doesn't care about fb's. +/* prepare/pin all the fb's bo's for scanout. */ int msm_framebuffer_prepare(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace) + struct msm_gem_address_space *aspace, + bool needs_dirtyfb) { + struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int ret, i, n = fb->format->num_planes; uint64_t iova; + if (needs_dirtyfb) + refcount_inc(&msm_fb->dirtyfb); + for (i = 0; i < n; i++) { ret = msm_gem_get_and_pin_iova(fb->obj[i], aspace, &iova); drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)", fb->base.id, i, iova, ret); @@ -70,10 +92,15 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb, } void msm_framebuffer_cleanup(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace) + struct msm_gem_address_space *aspace, + bool needed_dirtyfb) { + struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int i, n = fb->format->num_planes; + if (needed_dirtyfb) + refcount_dec(&msm_fb->dirtyfb); + for (i = 0; i < n; i++) msm_gem_unpin_iova(fb->obj[i], aspace); } From 0737ab95a0f4e0e133efe7cfdb0449bc35b3b893 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Sat, 26 Feb 2022 00:51:28 +0530 Subject: [PATCH 67/70] drm/msm: Use generic name for gpu resources Use generic name for resources like irq and kthread instead of hardware specific name to make it easier to grep. Signed-off-by: Akhil P Oommen Link: https://lore.kernel.org/r/20220226005021.v2.1.Id3d2e7391192c86d0783aeb307d3f9fb61f9efee@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 173ebd449f2fd..bacdabbaad963 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -844,7 +844,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, gpu->funcs = funcs; gpu->name = name; - gpu->worker = kthread_create_worker(0, "%s-worker", gpu->name); + gpu->worker = kthread_create_worker(0, "gpu-worker"); if (IS_ERR(gpu->worker)) { ret = PTR_ERR(gpu->worker); gpu->worker = NULL; @@ -882,7 +882,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, } ret = devm_request_irq(&pdev->dev, gpu->irq, irq_handler, - IRQF_TRIGGER_HIGH, gpu->name, gpu); + IRQF_TRIGGER_HIGH, "gpu-irq", gpu); if (ret) { DRM_DEV_ERROR(drm->dev, "failed to request IRQ%u: %d\n", gpu->irq, ret); goto fail; From e2f76193958be91baed84583b2c638f8ca8b3bc2 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Sat, 26 Feb 2022 00:51:29 +0530 Subject: [PATCH 68/70] drm/msm/adreno: Generate name from chipid for 7c3 Use a gpu name which is sprintf'ed from the chipid for 7c3 gpu instead of hardcoding one. This helps to avoid code churn in case of a gpu rename. Signed-off-by: Akhil P Oommen Link: https://lore.kernel.org/r/20220226005021.v2.2.I9436e0e300f76b2e6c34136a0b902e8cfd73e0d6@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/adreno_device.c | 1 - drivers/gpu/drm/msm/adreno/adreno_gpu.c | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index fb261930ad1c7..89cfd84760d7e 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -318,7 +318,6 @@ static const struct adreno_info gpulist[] = { .hwcg = a660_hwcg, }, { .rev = ADRENO_REV(6, 3, 5, ANY_ID), - .name = "Adreno 7c Gen 3", .fw = { [ADRENO_FW_SQE] = "a660_sqe.fw", [ADRENO_FW_GMU] = "a660_gmu.bin", diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 58dfb23cf2afa..d5810195df71f 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -930,12 +930,23 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct adreno_platform_config *config = dev->platform_data; struct msm_gpu_config adreno_gpu_config = { 0 }; struct msm_gpu *gpu = &adreno_gpu->base; + struct adreno_rev *rev = &config->rev; + const char *gpu_name; adreno_gpu->funcs = funcs; adreno_gpu->info = adreno_info(config->rev); adreno_gpu->gmem = adreno_gpu->info->gmem; adreno_gpu->revn = adreno_gpu->info->revn; - adreno_gpu->rev = config->rev; + adreno_gpu->rev = *rev; + + gpu_name = adreno_gpu->info->name; + if (!gpu_name) { + gpu_name = devm_kasprintf(dev, GFP_KERNEL, "%d.%d.%d.%d", + rev->core, rev->major, rev->minor, + rev->patchid); + if (!gpu_name) + return -ENOMEM; + } adreno_gpu_config.ioname = "kgsl_3d0_reg_memory"; @@ -949,7 +960,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, pm_runtime_enable(dev); return msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base, - adreno_gpu->info->name, &adreno_gpu_config); + gpu_name, &adreno_gpu_config); } void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu) From c43de1aa6a08cde01926e372dc7b63a9b7095c7b Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Sat, 26 Feb 2022 00:51:30 +0530 Subject: [PATCH 69/70] drm/msm/a6xx: Add support for 7c3 SKUs Add support for 7c3 SKU detection using speedbin fuse. Signed-off-by: Akhil P Oommen Link: https://lore.kernel.org/r/20220226005021.v2.3.I6e89c014eb17f090f716fba662bdd33073920804@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 83e5c09c7d4b1..634306ef4baa4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1736,6 +1736,18 @@ static u32 a618_get_speed_bin(u32 fuse) return UINT_MAX; } +static u32 adreno_7c3_get_speed_bin(u32 fuse) +{ + if (fuse == 0) + return 0; + else if (fuse == 117) + return 0; + else if (fuse == 190) + return 1; + + return UINT_MAX; +} + static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse) { u32 val = UINT_MAX; @@ -1743,6 +1755,9 @@ static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse) if (adreno_cmp_rev(ADRENO_REV(6, 1, 8, ANY_ID), rev)) val = a618_get_speed_bin(fuse); + if (adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), rev)) + val = adreno_7c3_get_speed_bin(fuse); + if (val == UINT_MAX) { DRM_DEV_ERROR(dev, "missing support for speed-bin: %u. Some OPPs may not be supported by hardware", From afab9d91d872819f98a792c32c302d9e3261f1a1 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Sat, 26 Feb 2022 00:51:31 +0530 Subject: [PATCH 70/70] drm/msm/adreno: Expose speedbin to userspace Expose speedbin through MSM_PARAM_CHIP_ID parameter to help userspace identify the sku. Signed-off-by: Akhil P Oommen Link: https://lore.kernel.org/r/20220226005021.v2.4.I86c32730e08cba9e5c83f02ec17885124d45fa56@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 3 +-- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 21 +++++++++++++++++---- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 3 +++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 634306ef4baa4..7d23c741db4ad 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -10,7 +10,6 @@ #include #include -#include #include #define GPU_PAS_ID 13 @@ -1774,7 +1773,7 @@ static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev) u32 speedbin; int ret; - ret = nvmem_cell_read_variable_le_u32(dev, "speed_bin", &speedbin); + ret = adreno_read_speedbin(dev, &speedbin); /* * -ENOENT means that the platform doesn't support speedbin which is * fine diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index d5810195df71f..15c8997b72516 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "adreno_gpu.h" #include "a6xx_gpu.h" @@ -243,10 +244,12 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, *value = !adreno_is_a650_family(adreno_gpu) ? 0x100000 : 0; return 0; case MSM_PARAM_CHIP_ID: - *value = adreno_gpu->rev.patchid | - (adreno_gpu->rev.minor << 8) | - (adreno_gpu->rev.major << 16) | - (adreno_gpu->rev.core << 24); + *value = (uint64_t) adreno_gpu->rev.patchid | + (uint64_t) (adreno_gpu->rev.minor << 8) | + (uint64_t) (adreno_gpu->rev.major << 16) | + (uint64_t) (adreno_gpu->rev.core << 24); + if (!adreno_gpu->info->revn) + *value |= ((uint64_t) adreno_gpu->speedbin) << 32; return 0; case MSM_PARAM_MAX_FREQ: *value = adreno_gpu->base.fast_rate; @@ -922,6 +925,11 @@ void adreno_gpu_ocmem_cleanup(struct adreno_ocmem *adreno_ocmem) adreno_ocmem->hdl); } +int adreno_read_speedbin(struct device *dev, u32 *speedbin) +{ + return nvmem_cell_read_variable_le_u32(dev, "speed_bin", speedbin); +} + int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct adreno_gpu *adreno_gpu, const struct adreno_gpu_funcs *funcs, int nr_rings) @@ -932,6 +940,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct msm_gpu *gpu = &adreno_gpu->base; struct adreno_rev *rev = &config->rev; const char *gpu_name; + u32 speedbin; adreno_gpu->funcs = funcs; adreno_gpu->info = adreno_info(config->rev); @@ -939,6 +948,10 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, adreno_gpu->revn = adreno_gpu->info->revn; adreno_gpu->rev = *rev; + if (adreno_read_speedbin(dev, &speedbin) || !speedbin) + speedbin = 0xffff; + adreno_gpu->speedbin = (uint16_t) (0xffff & speedbin); + gpu_name = adreno_gpu->info->name; if (!gpu_name) { gpu_name = devm_kasprintf(dev, GFP_KERNEL, "%d.%d.%d.%d", diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 432590036b318..b1ee453d627de 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -80,6 +80,7 @@ struct adreno_gpu { const struct adreno_info *info; uint32_t gmem; /* actual gmem size */ uint32_t revn; /* numeric revision name */ + uint16_t speedbin; const struct adreno_gpu_funcs *funcs; /* interesting register offsets to dump: */ @@ -325,6 +326,8 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu, void adreno_set_llc_attributes(struct iommu_domain *iommu); +int adreno_read_speedbin(struct device *dev, u32 *speedbin); + /* * For a5xx and a6xx targets load the zap shader that is used to pull the GPU * out of secure mode