diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 17:39:57 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 17:39:57 +0000 |
commit | dc50eab76b709d68175a358d6e23a5a3890764d3 (patch) | |
tree | c754d0390db060af0213ff994f0ac310e4cfd6e9 /drivers/gpu/drm/msm | |
parent | Adding debian version 6.6.15-2. (diff) | |
download | linux-dc50eab76b709d68175a358d6e23a5a3890764d3.tar.xz linux-dc50eab76b709d68175a358d6e23a5a3890764d3.zip |
Merging upstream version 6.7.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/gpu/drm/msm')
93 files changed, 2525 insertions, 1536 deletions
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 6309a857ca..ad70b611b4 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -6,6 +6,7 @@ config DRM_MSM depends on ARCH_QCOM || SOC_IMX5 || COMPILE_TEST depends on COMMON_CLK depends on IOMMU_SUPPORT + depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n depends on QCOM_OCMEM || QCOM_OCMEM=n depends on QCOM_LLCC || QCOM_LLCC=n depends on QCOM_COMMAND_DB || QCOM_COMMAND_DB=n diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 8d02d8c330..49671364fd 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -106,6 +106,7 @@ msm-y += \ msm_gpu_devfreq.o \ msm_io_utils.o \ msm_iommu.o \ + msm_kms.o \ msm_perf.o \ msm_rd.o \ msm_ringbuffer.o \ diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h b/drivers/gpu/drm/msm/adreno/a6xx.xml.h index 1c051535fd..863b5e3b0e 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx.xml.h +++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h @@ -1114,6 +1114,12 @@ enum a6xx_tex_type { #define REG_A6XX_CP_MISC_CNTL 0x00000840 #define REG_A6XX_CP_APRIV_CNTL 0x00000844 +#define A6XX_CP_APRIV_CNTL_CDWRITE 0x00000040 +#define A6XX_CP_APRIV_CNTL_CDREAD 0x00000020 +#define A6XX_CP_APRIV_CNTL_RBRPWB 0x00000008 +#define A6XX_CP_APRIV_CNTL_RBPRIVLEVEL 0x00000004 +#define A6XX_CP_APRIV_CNTL_RBFETCH 0x00000002 +#define A6XX_CP_APRIV_CNTL_ICACHE 0x00000001 #define REG_A6XX_CP_PREEMPT_THRESHOLD 0x000008c0 @@ -1939,6 +1945,8 @@ static inline uint32_t REG_A6XX_RBBM_PERFCTR_RBBM_SEL(uint32_t i0) { return 0x00 #define REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE 0x00000122 +#define REG_A7XX_RBBM_CLOCK_HYST2_VFD 0x0000012f + #define REG_A6XX_RBBM_LPAC_GBIF_CLIENT_QOS_CNTL 0x000005ff #define REG_A6XX_DBGC_CFG_DBGBUS_SEL_A 0x00000600 @@ -8252,5 +8260,6 @@ static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15(uint32_t val) #define REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_1 0x00000002 +#define REG_A7XX_CX_MISC_TCM_RET_CNTL 0x00000039 #endif /* A6XX_XML */ diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 7923129363..8c4900444b 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. */ +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/interconnect.h> #include <linux/of_platform.h> @@ -202,9 +203,10 @@ int a6xx_gmu_wait_for_idle(struct a6xx_gmu *gmu) static int a6xx_gmu_start(struct a6xx_gmu *gmu) { + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + u32 mask, reset_val, val; int ret; - u32 val; - u32 mask, reset_val; val = gmu_read(gmu, REG_A6XX_GMU_CM3_DTCM_START + 0xff8); if (val <= 0x20010004) { @@ -220,7 +222,11 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu) /* Set the log wptr index * note: downstream saves the value in poweroff and restores it here */ - gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP, 0); + if (adreno_is_a7xx(adreno_gpu)) + gmu_write(gmu, REG_A6XX_GMU_GENERAL_9, 0); + else + gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP, 0); + gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 0); @@ -513,6 +519,7 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; struct platform_device *pdev = to_platform_device(gmu->dev); void __iomem *pdcptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc"); + u32 seqmem0_drv0_reg = REG_A6XX_RSCC_SEQ_MEM_0_DRV0; void __iomem *seqptr = NULL; uint32_t pdc_address_offset; bool pdc_in_aop = false; @@ -520,7 +527,9 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) if (IS_ERR(pdcptr)) goto err; - if (adreno_is_a650(adreno_gpu) || adreno_is_a660_family(adreno_gpu)) + if (adreno_is_a650(adreno_gpu) || + adreno_is_a660_family(adreno_gpu) || + adreno_is_a7xx(adreno_gpu)) pdc_in_aop = true; else if (adreno_is_a618(adreno_gpu) || adreno_is_a640_family(adreno_gpu)) pdc_address_offset = 0x30090; @@ -544,20 +553,26 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0); gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 2, 0); gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 2, 0); - gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 4, 0x80000000); + gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 4, + adreno_is_a740_family(adreno_gpu) ? 0x80000021 : 0x80000000); gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 4, 0); gmu_write_rscc(gmu, REG_A6XX_RSCC_OVERRIDE_START_ADDR, 0); gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510); gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); + /* The second spin of A7xx GPUs messed with some register offsets.. */ + if (adreno_is_a740_family(adreno_gpu)) + seqmem0_drv0_reg = REG_A7XX_RSCC_SEQ_MEM_0_DRV0_A740; + /* Load RSC sequencer uCode for sleep and wakeup */ - if (adreno_is_a650_family(adreno_gpu)) { - gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xeaaae5a0); - gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xe1a1ebab); - gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xa2e0a581); - gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xecac82e2); - gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020edad); + if (adreno_is_a650_family(adreno_gpu) || + adreno_is_a7xx(adreno_gpu)) { + gmu_write_rscc(gmu, seqmem0_drv0_reg, 0xeaaae5a0); + gmu_write_rscc(gmu, seqmem0_drv0_reg + 1, 0xe1a1ebab); + gmu_write_rscc(gmu, seqmem0_drv0_reg + 2, 0xa2e0a581); + gmu_write_rscc(gmu, seqmem0_drv0_reg + 3, 0xecac82e2); + gmu_write_rscc(gmu, seqmem0_drv0_reg + 4, 0x0020edad); } else { gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xa7a506a0); gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xa1e6a6e7); @@ -637,11 +652,18 @@ err: /* Set up the idle state for the GMU */ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu) { + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + /* Disable GMU WB/RB buffer */ gmu_write(gmu, REG_A6XX_GMU_SYS_BUS_CONFIG, 0x1); gmu_write(gmu, REG_A6XX_GMU_ICACHE_CONFIG, 0x1); gmu_write(gmu, REG_A6XX_GMU_DCACHE_CONFIG, 0x1); + /* A7xx knows better by default! */ + if (adreno_is_a7xx(adreno_gpu)) + return; + gmu_write(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0x9c40400); switch (gmu->idle_level) { @@ -698,7 +720,7 @@ static int a6xx_gmu_fw_load(struct a6xx_gmu *gmu) u32 itcm_base = 0x00000000; u32 dtcm_base = 0x00040000; - if (adreno_is_a650_family(adreno_gpu)) + if (adreno_is_a650_family(adreno_gpu) || adreno_is_a7xx(adreno_gpu)) dtcm_base = 0x10004000; if (gmu->legacy) { @@ -747,14 +769,22 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) { struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + u32 fence_range_lower, fence_range_upper; + u32 chipid, chipid_min = 0; int ret; - u32 chipid; - if (adreno_is_a650_family(adreno_gpu)) { + /* Vote veto for FAL10 */ + if (adreno_is_a650_family(adreno_gpu) || adreno_is_a7xx(adreno_gpu)) { gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_CX_FALNEXT_INTF, 1); gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF, 1); } + /* Turn on TCM (Tightly Coupled Memory) retention */ + if (adreno_is_a7xx(adreno_gpu)) + a6xx_llc_write(a6xx_gpu, REG_A7XX_CX_MISC_TCM_RET_CNTL, 1); + else + gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1); + if (state == GMU_WARM_BOOT) { ret = a6xx_rpmh_start(gmu); if (ret) @@ -764,9 +794,6 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) "GMU firmware is not loaded\n")) return -ENOENT; - /* Turn on register retention */ - gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1); - ret = a6xx_rpmh_start(gmu); if (ret) return ret; @@ -776,6 +803,7 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) return ret; } + /* Clear init result to make sure we are getting a fresh value */ gmu_write(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, 0); gmu_write(gmu, REG_A6XX_GMU_CM3_BOOT_CONFIG, 0x02); @@ -783,8 +811,18 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) gmu_write(gmu, REG_A6XX_GMU_HFI_QTBL_ADDR, gmu->hfi.iova); gmu_write(gmu, REG_A6XX_GMU_HFI_QTBL_INFO, 1); + if (adreno_is_a7xx(adreno_gpu)) { + fence_range_upper = 0x32; + fence_range_lower = 0x8a0; + } else { + fence_range_upper = 0xa; + fence_range_lower = 0xa0; + } + gmu_write(gmu, REG_A6XX_GMU_AHB_FENCE_RANGE_0, - (1 << 31) | (0xa << 18) | (0xa0)); + BIT(31) | + FIELD_PREP(GENMASK(30, 18), fence_range_upper) | + FIELD_PREP(GENMASK(17, 0), fence_range_lower)); /* * Snapshots toggle the NMI bit which will result in a jump to the NMI @@ -792,21 +830,49 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) */ gmu_write(gmu, REG_A6XX_GMU_CM3_CFG, 0x4052); - /* - * Note that the GMU has a slightly different layout for - * chip_id, for whatever reason, so a bit of massaging - * is needed. The upper 16b are the same, but minor and - * patchid are packed in four bits each with the lower - * 8b unused: - */ - chipid = adreno_gpu->chip_id & 0xffff0000; - chipid |= (adreno_gpu->chip_id << 4) & 0xf000; /* minor */ - chipid |= (adreno_gpu->chip_id << 8) & 0x0f00; /* patchid */ + /* NOTE: A730 may also fall in this if-condition with a future GMU fw update. */ + if (adreno_is_a7xx(adreno_gpu) && !adreno_is_a730(adreno_gpu)) { + /* A7xx GPUs have obfuscated chip IDs. Use constant maj = 7 */ + chipid = FIELD_PREP(GENMASK(31, 24), 0x7); + + /* + * The min part has a 1-1 mapping for each GPU SKU. + * This chipid that the GMU expects corresponds to the "GENX_Y_Z" naming, + * where X = major, Y = minor, Z = patchlevel, e.g. GEN7_2_1 for prod A740. + */ + if (adreno_is_a740(adreno_gpu)) + chipid_min = 2; + else + return -EINVAL; + + chipid |= FIELD_PREP(GENMASK(23, 16), chipid_min); - gmu_write(gmu, REG_A6XX_GMU_HFI_SFR_ADDR, chipid); + /* Get the patchid (which may vary) from the device tree */ + chipid |= FIELD_PREP(GENMASK(15, 8), adreno_patchid(adreno_gpu)); + } else { + /* + * Note that the GMU has a slightly different layout for + * chip_id, for whatever reason, so a bit of massaging + * is needed. The upper 16b are the same, but minor and + * patchid are packed in four bits each with the lower + * 8b unused: + */ + chipid = adreno_gpu->chip_id & 0xffff0000; + chipid |= (adreno_gpu->chip_id << 4) & 0xf000; /* minor */ + chipid |= (adreno_gpu->chip_id << 8) & 0x0f00; /* patchid */ + } - gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_MSG, - gmu->log.iova | (gmu->log.size / SZ_4K - 1)); + if (adreno_is_a7xx(adreno_gpu)) { + gmu_write(gmu, REG_A6XX_GMU_GENERAL_10, chipid); + gmu_write(gmu, REG_A6XX_GMU_GENERAL_8, + (gmu->log.iova & GENMASK(31, 12)) | + ((gmu->log.size / SZ_4K - 1) & GENMASK(7, 0))); + } else { + gmu_write(gmu, REG_A6XX_GMU_HFI_SFR_ADDR, chipid); + + gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_MSG, + gmu->log.iova | (gmu->log.size / SZ_4K - 1)); + } /* Set up the lowest idle level on the GMU */ a6xx_gmu_power_config(gmu); @@ -857,17 +923,23 @@ static void a6xx_gmu_irq_disable(struct a6xx_gmu *gmu) static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu) { - u32 val; + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + u32 val, seqmem_off = 0; + + /* The second spin of A7xx GPUs messed with some register offsets.. */ + if (adreno_is_a740_family(adreno_gpu)) + seqmem_off = 4; /* Make sure there are no outstanding RPMh votes */ - gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS0_DRV0_STATUS, val, - (val & 1), 100, 10000); - gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS1_DRV0_STATUS, val, - (val & 1), 100, 10000); - gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS2_DRV0_STATUS, val, - (val & 1), 100, 10000); - gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS, val, - (val & 1), 100, 1000); + gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS0_DRV0_STATUS + seqmem_off, + val, (val & 1), 100, 10000); + gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS1_DRV0_STATUS + seqmem_off, + val, (val & 1), 100, 10000); + gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS2_DRV0_STATUS + seqmem_off, + val, (val & 1), 100, 10000); + gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off, + val, (val & 1), 100, 1000); } /* Force the GMU off in case it isn't responsive */ @@ -950,6 +1022,14 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) gmu->hung = false; + /* Notify AOSS about the ACD state (unimplemented for now => disable it) */ + if (!IS_ERR(gmu->qmp)) { + ret = qmp_send(gmu->qmp, "{class: gpu, res: acd, val: %d}", + 0 /* Hardcode ACD to be disabled for now */); + if (ret) + dev_err(gmu->dev, "failed to send GPU ACD state\n"); + } + /* Turn on the resources */ pm_runtime_get_sync(gmu->dev); @@ -963,7 +1043,8 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) /* Use a known rate to bring up the GMU */ clk_set_rate(gmu->core_clk, 200000000); - clk_set_rate(gmu->hub_clk, 150000000); + clk_set_rate(gmu->hub_clk, adreno_is_a740_family(adreno_gpu) ? + 200000000 : 150000000); ret = clk_bulk_prepare_enable(gmu->nr_clocks, gmu->clocks); if (ret) { pm_runtime_put(gmu->gxpd); @@ -980,15 +1061,19 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) enable_irq(gmu->gmu_irq); /* Check to see if we are doing a cold or warm boot */ - status = gmu_read(gmu, REG_A6XX_GMU_GENERAL_7) == 1 ? - GMU_WARM_BOOT : GMU_COLD_BOOT; - - /* - * Warm boot path does not work on newer GPUs - * Presumably this is because icache/dcache regions must be restored - */ - if (!gmu->legacy) + if (adreno_is_a7xx(adreno_gpu)) { + status = a6xx_llc_read(a6xx_gpu, REG_A7XX_CX_MISC_TCM_RET_CNTL) == 1 ? + GMU_WARM_BOOT : GMU_COLD_BOOT; + } else if (gmu->legacy) { + status = gmu_read(gmu, REG_A6XX_GMU_GENERAL_7) == 1 ? + GMU_WARM_BOOT : GMU_COLD_BOOT; + } else { + /* + * Warm boot path does not work on newer A6xx GPUs + * Presumably this is because icache/dcache regions must be restored + */ status = GMU_COLD_BOOT; + } ret = a6xx_gmu_fw_start(gmu, status); if (ret) @@ -1473,6 +1558,9 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) dev_pm_domain_detach(gmu->gxpd, false); } + if (!IS_ERR_OR_NULL(gmu->qmp)) + qmp_put(gmu->qmp); + iounmap(gmu->mmio); if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "rscc")) iounmap(gmu->rscc); @@ -1569,6 +1657,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; struct a6xx_gmu *gmu = &a6xx_gpu->gmu; struct platform_device *pdev = of_find_device_by_node(node); + struct device_link *link; int ret; if (!pdev) @@ -1600,7 +1689,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) * are otherwise unused by a660. */ gmu->dummy.size = SZ_4K; - if (adreno_is_a660_family(adreno_gpu)) { + if (adreno_is_a660_family(adreno_gpu) || + adreno_is_a7xx(adreno_gpu)) { ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_4K * 7, 0x60400000, "debug"); if (ret) @@ -1616,7 +1706,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) goto err_memory; /* Note that a650 family also includes a660 family: */ - if (adreno_is_a650_family(adreno_gpu)) { + if (adreno_is_a650_family(adreno_gpu) || + adreno_is_a7xx(adreno_gpu)) { ret = a6xx_gmu_memory_alloc(gmu, &gmu->icache, SZ_16M - SZ_16K, 0x04000, "icache"); if (ret) @@ -1664,7 +1755,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) goto err_memory; } - if (adreno_is_a650_family(adreno_gpu)) { + if (adreno_is_a650_family(adreno_gpu) || + adreno_is_a7xx(adreno_gpu)) { gmu->rscc = a6xx_gmu_get_mmio(pdev, "rscc"); if (IS_ERR(gmu->rscc)) { ret = -ENODEV; @@ -1689,12 +1781,18 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) goto err_mmio; } - if (!device_link_add(gmu->dev, gmu->cxpd, - DL_FLAG_PM_RUNTIME)) { + link = device_link_add(gmu->dev, gmu->cxpd, DL_FLAG_PM_RUNTIME); + if (!link) { ret = -ENODEV; goto detach_cxpd; } + gmu->qmp = qmp_get(gmu->dev); + if (IS_ERR(gmu->qmp) && adreno_is_a7xx(adreno_gpu)) { + ret = PTR_ERR(gmu->qmp); + goto remove_device_link; + } + init_completion(&gmu->pd_gate); complete_all(&gmu->pd_gate); gmu->pd_nb.notifier_call = cxpd_notifier_cb; @@ -1718,6 +1816,9 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) return 0; +remove_device_link: + device_link_del(link); + detach_cxpd: dev_pm_domain_detach(gmu->cxpd, false); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index 236f81a43c..592b296aab 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -8,6 +8,7 @@ #include <linux/iopoll.h> #include <linux/interrupt.h> #include <linux/notifier.h> +#include <linux/soc/qcom/qcom_aoss.h> #include "msm_drv.h" #include "a6xx_hfi.h" @@ -96,6 +97,8 @@ struct a6xx_gmu { /* For power domain callback */ struct notifier_block pd_nb; struct completion pd_gate; + + struct qmp *qmp; }; static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h index fcd9eb53ba..5b66efafc9 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h @@ -360,6 +360,12 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val) #define REG_A6XX_GMU_GENERAL_7 0x000051cc +#define REG_A6XX_GMU_GENERAL_8 0x000051cd + +#define REG_A6XX_GMU_GENERAL_9 0x000051ce + +#define REG_A6XX_GMU_GENERAL_10 0x000051cf + #define REG_A6XX_GMU_ISENSE_CTRL 0x0000515d #define REG_A6XX_GPU_CS_ENABLE_REG 0x00008920 @@ -471,6 +477,8 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val) #define REG_A6XX_RSCC_SEQ_BUSY_DRV0 0x00000101 +#define REG_A7XX_RSCC_SEQ_MEM_0_DRV0_A740 0x00000154 + #define REG_A6XX_RSCC_SEQ_MEM_0_DRV0 0x00000180 #define REG_A6XX_RSCC_TCS0_DRV0_STATUS 0x00000346 diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 522ca7fe67..500ed2d183 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -103,6 +103,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, struct msm_ringbuffer *ring, struct msm_file_private *ctx) { bool sysprof = refcount_read(&a6xx_gpu->base.base.sysprof_active) > 1; + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; phys_addr_t ttbr; u32 asid; u64 memptr = rbmemptr(ring, ttbr0); @@ -114,9 +115,11 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, return; if (!sysprof) { - /* Turn off protected mode to write to special registers */ - OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); - OUT_RING(ring, 0); + if (!adreno_is_a7xx(adreno_gpu)) { + /* Turn off protected mode to write to special registers */ + OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); + OUT_RING(ring, 0); + } OUT_PKT4(ring, REG_A6XX_RBBM_PERFCTR_SRAM_INIT_CMD, 1); OUT_RING(ring, 1); @@ -142,6 +145,16 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, OUT_RING(ring, (asid << 16) | upper_32_bits(ttbr)); /* + * Sync both threads after switching pagetables and enable BR only + * to make sure BV doesn't race ahead while BR is still switching + * pagetables. + */ + if (adreno_is_a7xx(&a6xx_gpu->base)) { + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BR); + } + + /* * And finally, trigger a uche flush to be sure there isn't anything * lingering in that part of the GPU */ @@ -163,9 +176,11 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, OUT_RING(ring, CP_WAIT_REG_MEM_4_MASK(0x1)); OUT_RING(ring, CP_WAIT_REG_MEM_5_DELAY_LOOP_CYCLES(0)); - /* Re-enable protected mode: */ - OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); - OUT_RING(ring, 1); + if (!adreno_is_a7xx(adreno_gpu)) { + /* Re-enable protected mode: */ + OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); + OUT_RING(ring, 1); + } } } @@ -252,6 +267,133 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) a6xx_flush(gpu, ring); } +static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) +{ + unsigned int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT; + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + struct msm_ringbuffer *ring = submit->ring; + unsigned int i, ibs = 0; + + /* + * Toggle concurrent binning for pagetable switch and set the thread to + * BR since only it can execute the pagetable switch packets. + */ + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BR); + + a6xx_set_pagetable(a6xx_gpu, ring, submit->queue->ctx); + + get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0), + rbmemptr_stats(ring, index, cpcycles_start)); + get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_COUNTER, + rbmemptr_stats(ring, index, alwayson_start)); + + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, CP_SET_THREAD_BOTH); + + OUT_PKT7(ring, CP_SET_MARKER, 1); + OUT_RING(ring, 0x101); /* IFPC disable */ + + OUT_PKT7(ring, CP_SET_MARKER, 1); + OUT_RING(ring, 0x00d); /* IB1LIST start */ + + /* Submit the commands */ + for (i = 0; i < submit->nr_cmds; i++) { + switch (submit->cmd[i].type) { + case MSM_SUBMIT_CMD_IB_TARGET_BUF: + break; + case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: + if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) + break; + fallthrough; + case MSM_SUBMIT_CMD_BUF: + OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3); + OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); + OUT_RING(ring, upper_32_bits(submit->cmd[i].iova)); + OUT_RING(ring, submit->cmd[i].size); + ibs++; + break; + } + + /* + * Periodically update shadow-wptr if needed, so that we + * can see partial progress of submits with large # of + * cmds.. otherwise we could needlessly stall waiting for + * ringbuffer state, simply due to looking at a shadow + * rptr value that has not been updated + */ + if ((ibs % 32) == 0) + update_shadow_rptr(gpu, ring); + } + + OUT_PKT7(ring, CP_SET_MARKER, 1); + OUT_RING(ring, 0x00e); /* IB1LIST end */ + + get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0), + rbmemptr_stats(ring, index, cpcycles_end)); + get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_COUNTER, + rbmemptr_stats(ring, index, alwayson_end)); + + /* Write the fence to the scratch register */ + OUT_PKT4(ring, REG_A6XX_CP_SCRATCH_REG(2), 1); + OUT_RING(ring, submit->seqno); + + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, CP_SET_THREAD_BR); + + OUT_PKT7(ring, CP_EVENT_WRITE, 1); + OUT_RING(ring, CCU_INVALIDATE_DEPTH); + + OUT_PKT7(ring, CP_EVENT_WRITE, 1); + OUT_RING(ring, CCU_INVALIDATE_COLOR); + + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, CP_SET_THREAD_BV); + + /* + * Make sure the timestamp is committed once BV pipe is + * completely done with this submission. + */ + OUT_PKT7(ring, CP_EVENT_WRITE, 4); + OUT_RING(ring, CACHE_CLEAN | BIT(27)); + OUT_RING(ring, lower_32_bits(rbmemptr(ring, bv_fence))); + OUT_RING(ring, upper_32_bits(rbmemptr(ring, bv_fence))); + OUT_RING(ring, submit->seqno); + + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, CP_SET_THREAD_BR); + + /* + * This makes sure that BR doesn't race ahead and commit + * timestamp to memstore while BV is still processing + * this submission. + */ + OUT_PKT7(ring, CP_WAIT_TIMESTAMP, 4); + OUT_RING(ring, 0); + OUT_RING(ring, lower_32_bits(rbmemptr(ring, bv_fence))); + OUT_RING(ring, upper_32_bits(rbmemptr(ring, bv_fence))); + OUT_RING(ring, submit->seqno); + + /* write the ringbuffer timestamp */ + OUT_PKT7(ring, CP_EVENT_WRITE, 4); + OUT_RING(ring, CACHE_CLEAN | CP_EVENT_WRITE_0_IRQ | BIT(27)); + OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence))); + OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence))); + OUT_RING(ring, submit->seqno); + + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, CP_SET_THREAD_BOTH); + + OUT_PKT7(ring, CP_SET_MARKER, 1); + OUT_RING(ring, 0x100); /* IFPC enable */ + + trace_msm_gpu_submit_flush(submit, + gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER)); + + a6xx_flush(gpu, ring); +} + const struct adreno_reglist a612_hwcg[] = { {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222}, {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, @@ -695,6 +837,121 @@ const struct adreno_reglist a690_hwcg[] = { {} }; +const struct adreno_reglist a730_hwcg[] = { + { REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222 }, + { REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02022222 }, + { REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf }, + { REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080 }, + { REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222220 }, + { REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222 }, + { REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222 }, + { REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00222222 }, + { REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777 }, + { REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777 }, + { REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777 }, + { REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777 }, + { REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111 }, + { REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111 }, + { REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111 }, + { REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111 }, + { REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222 }, + { REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004 }, + { REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002 }, + { REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222 }, + { REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222 }, + { REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220 }, + { REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x44000f00 }, + { REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022 }, + { REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00555555 }, + { REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011 }, + { REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00440044 }, + { REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222 }, + { REG_A7XX_RBBM_CLOCK_MODE2_GRAS, 0x00000222 }, + { REG_A7XX_RBBM_CLOCK_MODE_BV_GRAS, 0x00222222 }, + { REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222223 }, + { REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222 }, + { REG_A7XX_RBBM_CLOCK_MODE_BV_GPC, 0x00222222 }, + { REG_A7XX_RBBM_CLOCK_MODE_BV_VFD, 0x00002222 }, + { REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000 }, + { REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004 }, + { REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000 }, + { REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000 }, + { REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200 }, + { REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222 }, + { REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222 }, + { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000 }, + { REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000 }, + { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002 }, + { REG_A7XX_RBBM_CLOCK_MODE_BV_LRZ, 0x55555552 }, + { REG_A7XX_RBBM_CLOCK_MODE_CP, 0x00000223 }, + { REG_A6XX_RBBM_CLOCK_CNTL, 0x8aa8aa82 }, + { REG_A6XX_RBBM_ISDB_CNT, 0x00000182 }, + { REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000 }, + { REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000 }, + { REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222 }, + { REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111 }, + { REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555 }, + {}, +}; + +const struct adreno_reglist a740_hwcg[] = { + { REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222 }, + { REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x22022222 }, + { REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x003cf3cf }, + { REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080 }, + { REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222220 }, + { REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222 }, + { REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222 }, + { REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00222222 }, + { REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777 }, + { REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777 }, + { REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777 }, + { REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777 }, + { REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111 }, + { REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111 }, + { REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111 }, + { REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111 }, + { REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222 }, + { REG_A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x00222222 }, + { REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000444 }, + { REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000222 }, + { REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222 }, + { REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222 }, + { REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220 }, + { REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x44000f00 }, + { REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022 }, + { REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00555555 }, + { REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011 }, + { REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00440044 }, + { REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222 }, + { REG_A7XX_RBBM_CLOCK_MODE2_GRAS, 0x00000222 }, + { REG_A7XX_RBBM_CLOCK_MODE_BV_GRAS, 0x00222222 }, + { REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222223 }, + { REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00222222 }, + { REG_A7XX_RBBM_CLOCK_MODE_BV_GPC, 0x00222222 }, + { REG_A7XX_RBBM_CLOCK_MODE_BV_VFD, 0x00002222 }, + { REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000 }, + { REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004 }, + { REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000 }, + { REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00000000 }, + { REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200 }, + { REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00000000 }, + { REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222 }, + { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000 }, + { REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000 }, + { REG_A7XX_RBBM_CLOCK_MODE_BV_LRZ, 0x55555552 }, + { REG_A7XX_RBBM_CLOCK_HYST2_VFD, 0x00000000 }, + { REG_A7XX_RBBM_CLOCK_MODE_CP, 0x00000222 }, + { REG_A6XX_RBBM_CLOCK_CNTL, 0x8aa8aa82 }, + { REG_A6XX_RBBM_ISDB_CNT, 0x00000182 }, + { REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000 }, + { REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000 }, + { REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222 }, + { REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111 }, + { REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555 }, + {}, +}; + static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); @@ -702,7 +959,7 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state) struct a6xx_gmu *gmu = &a6xx_gpu->gmu; const struct adreno_reglist *reg; unsigned int i; - u32 val, clock_cntl_on; + u32 val, clock_cntl_on, cgc_mode; if (!adreno_gpu->info->hwcg) return; @@ -714,6 +971,17 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state) else clock_cntl_on = 0x8aa8aa82; + if (adreno_is_a7xx(adreno_gpu)) { + cgc_mode = adreno_is_a740_family(adreno_gpu) ? 0x20222 : 0x20000; + + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL, + state ? cgc_mode : 0); + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL, + state ? 0x10111 : 0); + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL, + state ? 0x5555 : 0); + } + val = gpu_read(gpu, REG_A6XX_RBBM_CLOCK_CNTL); /* Don't re-program the registers if they are already correct */ @@ -721,14 +989,14 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state) return; /* Disable SP clock before programming HWCG registers */ - if (!adreno_is_a610(adreno_gpu)) + if (!adreno_is_a610(adreno_gpu) && !adreno_is_a7xx(adreno_gpu)) gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 1, 0); for (i = 0; (reg = &adreno_gpu->info->hwcg[i], reg->offset); i++) gpu_write(gpu, reg->offset, state ? reg->value : 0); /* Enable SP clock */ - if (!adreno_is_a610(adreno_gpu)) + if (!adreno_is_a610(adreno_gpu) && !adreno_is_a7xx(adreno_gpu)) gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 0, 1); gpu_write(gpu, REG_A6XX_RBBM_CLOCK_CNTL, state ? clock_cntl_on : 0); @@ -897,6 +1165,59 @@ static const u32 a690_protect[] = { A6XX_PROTECT_NORDWR(0x11c00, 0x00000), /*note: infiite range */ }; +static const u32 a730_protect[] = { + A6XX_PROTECT_RDONLY(0x00000, 0x04ff), + A6XX_PROTECT_RDONLY(0x0050b, 0x0058), + A6XX_PROTECT_NORDWR(0x0050e, 0x0000), + A6XX_PROTECT_NORDWR(0x00510, 0x0000), + A6XX_PROTECT_NORDWR(0x00534, 0x0000), + A6XX_PROTECT_RDONLY(0x005fb, 0x009d), + A6XX_PROTECT_NORDWR(0x00699, 0x01e9), + A6XX_PROTECT_NORDWR(0x008a0, 0x0008), + A6XX_PROTECT_NORDWR(0x008ab, 0x0024), + /* 0x008d0-0x008dd are unprotected on purpose for tools like perfetto */ + A6XX_PROTECT_RDONLY(0x008de, 0x0154), + A6XX_PROTECT_NORDWR(0x00900, 0x004d), + A6XX_PROTECT_NORDWR(0x0098d, 0x00b2), + A6XX_PROTECT_NORDWR(0x00a41, 0x01be), + A6XX_PROTECT_NORDWR(0x00df0, 0x0001), + A6XX_PROTECT_NORDWR(0x00e01, 0x0000), + A6XX_PROTECT_NORDWR(0x00e07, 0x0008), + A6XX_PROTECT_NORDWR(0x03c00, 0x00c3), + A6XX_PROTECT_RDONLY(0x03cc4, 0x1fff), + A6XX_PROTECT_NORDWR(0x08630, 0x01cf), + A6XX_PROTECT_NORDWR(0x08e00, 0x0000), + A6XX_PROTECT_NORDWR(0x08e08, 0x0000), + A6XX_PROTECT_NORDWR(0x08e50, 0x001f), + A6XX_PROTECT_NORDWR(0x08e80, 0x0280), + A6XX_PROTECT_NORDWR(0x09624, 0x01db), + A6XX_PROTECT_NORDWR(0x09e40, 0x0000), + A6XX_PROTECT_NORDWR(0x09e64, 0x000d), + A6XX_PROTECT_NORDWR(0x09e78, 0x0187), + A6XX_PROTECT_NORDWR(0x0a630, 0x01cf), + A6XX_PROTECT_NORDWR(0x0ae02, 0x0000), + A6XX_PROTECT_NORDWR(0x0ae50, 0x000f), + A6XX_PROTECT_NORDWR(0x0ae66, 0x0003), + A6XX_PROTECT_NORDWR(0x0ae6f, 0x0003), + A6XX_PROTECT_NORDWR(0x0b604, 0x0003), + A6XX_PROTECT_NORDWR(0x0ec00, 0x0fff), + A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff), + A6XX_PROTECT_NORDWR(0x18400, 0x0053), + A6XX_PROTECT_RDONLY(0x18454, 0x0004), + A6XX_PROTECT_NORDWR(0x18459, 0x1fff), + A6XX_PROTECT_NORDWR(0x1a459, 0x1fff), + A6XX_PROTECT_NORDWR(0x1c459, 0x1fff), + A6XX_PROTECT_NORDWR(0x1f400, 0x0443), + A6XX_PROTECT_RDONLY(0x1f844, 0x007b), + A6XX_PROTECT_NORDWR(0x1f860, 0x0000), + A6XX_PROTECT_NORDWR(0x1f878, 0x002a), + /* CP_PROTECT_REG[44, 46] are left untouched! */ + 0, + 0, + 0, + A6XX_PROTECT_NORDWR(0x1f8c0, 0x00000), +}; + static void a6xx_set_cp_protect(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); @@ -918,6 +1239,11 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu) count = ARRAY_SIZE(a660_protect); count_max = 48; BUILD_BUG_ON(ARRAY_SIZE(a660_protect) > 48); + } else if (adreno_is_a730(adreno_gpu) || adreno_is_a740(adreno_gpu)) { + regs = a730_protect; + count = ARRAY_SIZE(a730_protect); + count_max = 48; + BUILD_BUG_ON(ARRAY_SIZE(a730_protect) > 48); } else { regs = a6xx_protect; count = ARRAY_SIZE(a6xx_protect); @@ -984,7 +1310,11 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu) if (adreno_is_a640_family(adreno_gpu)) amsbc = 1; - if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu)) { + if (adreno_is_a650(adreno_gpu) || + adreno_is_a660(adreno_gpu) || + adreno_is_a690(adreno_gpu) || + adreno_is_a730(adreno_gpu) || + adreno_is_a740_family(adreno_gpu)) { /* TODO: get ddr type from bootloader and use 2 for LPDDR4 */ hbb_lo = 3; amsbc = 1; @@ -992,13 +1322,6 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu) uavflagprd_inv = 2; } - if (adreno_is_a690(adreno_gpu)) { - hbb_lo = 2; - amsbc = 1; - rgb565_predicator = 1; - uavflagprd_inv = 2; - } - if (adreno_is_7c3(adreno_gpu)) { hbb_lo = 1; amsbc = 1; @@ -1017,6 +1340,10 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu) uavflagprd_inv << 4 | min_acc_len << 3 | hbb_lo << 1 | ubwc_mode); + if (adreno_is_a7xx(adreno_gpu)) + gpu_write(gpu, REG_A7XX_GRAS_NC_MODE_CNTL, + FIELD_PREP(GENMASK(8, 5), hbb_lo)); + gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL, min_acc_len << 23 | hbb_lo << 21); } @@ -1049,6 +1376,55 @@ static int a6xx_cp_init(struct msm_gpu *gpu) return a6xx_idle(gpu, ring) ? 0 : -EINVAL; } +static int a7xx_cp_init(struct msm_gpu *gpu) +{ + struct msm_ringbuffer *ring = gpu->rb[0]; + u32 mask; + + /* Disable concurrent binning before sending CP init */ + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, BIT(27)); + + OUT_PKT7(ring, CP_ME_INIT, 7); + + /* Use multiple HW contexts */ + mask = BIT(0); + + /* Enable error detection */ + mask |= BIT(1); + + /* Set default reset state */ + mask |= BIT(3); + + /* Disable save/restore of performance counters across preemption */ + mask |= BIT(6); + + /* Enable the register init list with the spinlock */ + mask |= BIT(8); + + OUT_RING(ring, mask); + + /* Enable multiple hardware contexts */ + OUT_RING(ring, 0x00000003); + + /* Enable error detection */ + OUT_RING(ring, 0x20000000); + + /* Operation mode mask */ + OUT_RING(ring, 0x00000002); + + /* *Don't* send a power up reg list for concurrent binning (TODO) */ + /* Lo address */ + OUT_RING(ring, 0x00000000); + /* Hi address */ + OUT_RING(ring, 0x00000000); + /* BIT(31) set => read the regs from the list */ + OUT_RING(ring, 0x00000000); + + a6xx_flush(gpu, ring); + return a6xx_idle(gpu, ring) ? 0 : -EINVAL; +} + /* * Check that the microcode version is new enough to include several key * security fixes. Return true if the ucode is safe. @@ -1065,6 +1441,10 @@ static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu, if (IS_ERR(buf)) return false; + /* A7xx is safe! */ + if (adreno_is_a7xx(adreno_gpu)) + return true; + /* * Targets up to a640 (a618, a630 and a640) need to check for a * microcode version that is patched to support the whereami opcode or @@ -1181,22 +1561,46 @@ static int a6xx_zap_shader_init(struct msm_gpu *gpu) } #define A6XX_INT_MASK (A6XX_RBBM_INT_0_MASK_CP_AHB_ERROR | \ - A6XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNCFIFO_OVERFLOW | \ - A6XX_RBBM_INT_0_MASK_CP_HW_ERROR | \ - A6XX_RBBM_INT_0_MASK_CP_IB2 | \ - A6XX_RBBM_INT_0_MASK_CP_IB1 | \ - A6XX_RBBM_INT_0_MASK_CP_RB | \ - A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \ - A6XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW | \ - A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT | \ - A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ - A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR) + A6XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNCFIFO_OVERFLOW | \ + A6XX_RBBM_INT_0_MASK_CP_HW_ERROR | \ + A6XX_RBBM_INT_0_MASK_CP_IB2 | \ + A6XX_RBBM_INT_0_MASK_CP_IB1 | \ + A6XX_RBBM_INT_0_MASK_CP_RB | \ + A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \ + A6XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW | \ + A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT | \ + A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ + A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR) + +#define A7XX_INT_MASK (A6XX_RBBM_INT_0_MASK_CP_AHB_ERROR | \ + A6XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNCFIFO_OVERFLOW | \ + A6XX_RBBM_INT_0_MASK_RBBM_GPC_ERROR | \ + A6XX_RBBM_INT_0_MASK_CP_SW | \ + A6XX_RBBM_INT_0_MASK_CP_HW_ERROR | \ + A6XX_RBBM_INT_0_MASK_PM4CPINTERRUPT | \ + A6XX_RBBM_INT_0_MASK_CP_RB_DONE_TS | \ + A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \ + A6XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW | \ + A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT | \ + A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ + A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR | \ + A6XX_RBBM_INT_0_MASK_TSBWRITEERROR) + +#define A7XX_APRIV_MASK (A6XX_CP_APRIV_CNTL_ICACHE | \ + A6XX_CP_APRIV_CNTL_RBFETCH | \ + A6XX_CP_APRIV_CNTL_RBPRIVLEVEL | \ + A6XX_CP_APRIV_CNTL_RBRPWB) + +#define A7XX_BR_APRIVMASK (A7XX_APRIV_MASK | \ + A6XX_CP_APRIV_CNTL_CDREAD | \ + A6XX_CP_APRIV_CNTL_CDWRITE) static int hw_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); struct a6xx_gmu *gmu = &a6xx_gpu->gmu; + u64 gmem_range_min; int ret; if (!adreno_has_gmu_wrapper(adreno_gpu)) { @@ -1219,6 +1623,10 @@ static int hw_init(struct msm_gpu *gpu) mb(); } + /* Some GPUs are stubborn and take their sweet time to unhalt GBIF! */ + if (adreno_is_a7xx(adreno_gpu) && a6xx_has_gbif(adreno_gpu)) + spin_until(!gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK)); + gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_CNTL, 0); if (adreno_is_a619_holi(adreno_gpu)) @@ -1232,19 +1640,21 @@ static int hw_init(struct msm_gpu *gpu) gpu_write64(gpu, REG_A6XX_RBBM_SECVID_TSB_TRUSTED_BASE, 0x00000000); gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000); - /* Turn on 64 bit addressing for all blocks */ - gpu_write(gpu, REG_A6XX_CP_ADDR_MODE_CNTL, 0x1); - gpu_write(gpu, REG_A6XX_VSC_ADDR_MODE_CNTL, 0x1); - gpu_write(gpu, REG_A6XX_GRAS_ADDR_MODE_CNTL, 0x1); - gpu_write(gpu, REG_A6XX_RB_ADDR_MODE_CNTL, 0x1); - gpu_write(gpu, REG_A6XX_PC_ADDR_MODE_CNTL, 0x1); - gpu_write(gpu, REG_A6XX_HLSQ_ADDR_MODE_CNTL, 0x1); - gpu_write(gpu, REG_A6XX_VFD_ADDR_MODE_CNTL, 0x1); - gpu_write(gpu, REG_A6XX_VPC_ADDR_MODE_CNTL, 0x1); - gpu_write(gpu, REG_A6XX_UCHE_ADDR_MODE_CNTL, 0x1); - gpu_write(gpu, REG_A6XX_SP_ADDR_MODE_CNTL, 0x1); - gpu_write(gpu, REG_A6XX_TPL1_ADDR_MODE_CNTL, 0x1); - gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL, 0x1); + if (!adreno_is_a7xx(adreno_gpu)) { + /* Turn on 64 bit addressing for all blocks */ + gpu_write(gpu, REG_A6XX_CP_ADDR_MODE_CNTL, 0x1); + gpu_write(gpu, REG_A6XX_VSC_ADDR_MODE_CNTL, 0x1); + gpu_write(gpu, REG_A6XX_GRAS_ADDR_MODE_CNTL, 0x1); + gpu_write(gpu, REG_A6XX_RB_ADDR_MODE_CNTL, 0x1); + gpu_write(gpu, REG_A6XX_PC_ADDR_MODE_CNTL, 0x1); + gpu_write(gpu, REG_A6XX_HLSQ_ADDR_MODE_CNTL, 0x1); + gpu_write(gpu, REG_A6XX_VFD_ADDR_MODE_CNTL, 0x1); + gpu_write(gpu, REG_A6XX_VPC_ADDR_MODE_CNTL, 0x1); + gpu_write(gpu, REG_A6XX_UCHE_ADDR_MODE_CNTL, 0x1); + gpu_write(gpu, REG_A6XX_SP_ADDR_MODE_CNTL, 0x1); + gpu_write(gpu, REG_A6XX_TPL1_ADDR_MODE_CNTL, 0x1); + gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL, 0x1); + } /* enable hardware clockgating */ a6xx_set_hwcg(gpu, true); @@ -1252,12 +1662,14 @@ static int hw_init(struct msm_gpu *gpu) /* VBIF/GBIF start*/ if (adreno_is_a610(adreno_gpu) || adreno_is_a640_family(adreno_gpu) || - adreno_is_a650_family(adreno_gpu)) { + adreno_is_a650_family(adreno_gpu) || + adreno_is_a7xx(adreno_gpu)) { gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE0, 0x00071620); gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE1, 0x00071620); gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE2, 0x00071620); gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620); - gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x3); + gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, + adreno_is_a7xx(adreno_gpu) ? 0x2120212 : 0x3); } else { gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3); } @@ -1265,24 +1677,39 @@ static int hw_init(struct msm_gpu *gpu) if (adreno_is_a630(adreno_gpu)) gpu_write(gpu, REG_A6XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000009); + if (adreno_is_a7xx(adreno_gpu)) + gpu_write(gpu, REG_A6XX_UCHE_GBIF_GX_CONFIG, 0x10240e0); + /* Make all blocks contribute to the GPU BUSY perf counter */ gpu_write(gpu, REG_A6XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xffffffff); /* Disable L2 bypass in the UCHE */ - gpu_write64(gpu, REG_A6XX_UCHE_WRITE_RANGE_MAX, 0x0001ffffffffffc0llu); - gpu_write64(gpu, REG_A6XX_UCHE_TRAP_BASE, 0x0001fffffffff000llu); - gpu_write64(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE, 0x0001fffffffff000llu); + if (adreno_is_a7xx(adreno_gpu)) { + gpu_write64(gpu, REG_A6XX_UCHE_TRAP_BASE, 0x0001fffffffff000llu); + gpu_write64(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE, 0x0001fffffffff000llu); + } else { + gpu_write64(gpu, REG_A6XX_UCHE_WRITE_RANGE_MAX, 0x0001ffffffffffc0llu); + gpu_write64(gpu, REG_A6XX_UCHE_TRAP_BASE, 0x0001fffffffff000llu); + gpu_write64(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE, 0x0001fffffffff000llu); + } + + if (!(adreno_is_a650_family(adreno_gpu) || + adreno_is_a730(adreno_gpu))) { + gmem_range_min = adreno_is_a740_family(adreno_gpu) ? SZ_16M : SZ_1M; - if (!adreno_is_a650_family(adreno_gpu)) { /* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */ - gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN, 0x00100000); + gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN, gmem_range_min); gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX, - 0x00100000 + adreno_gpu->info->gmem - 1); + gmem_range_min + adreno_gpu->info->gmem - 1); } - gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804); - gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4); + if (adreno_is_a7xx(adreno_gpu)) + gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, BIT(23)); + else { + gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804); + gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4); + } if (adreno_is_a640_family(adreno_gpu) || adreno_is_a650_family(adreno_gpu)) { gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x02000140); @@ -1290,7 +1717,7 @@ static int hw_init(struct msm_gpu *gpu) } else if (adreno_is_a610(adreno_gpu)) { gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x00800060); gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x40201b16); - } else { + } else if (!adreno_is_a7xx(adreno_gpu)) { gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0); gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c); } @@ -1302,13 +1729,15 @@ static int hw_init(struct msm_gpu *gpu) if (adreno_is_a610(adreno_gpu)) { gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 48); gpu_write(gpu, REG_A6XX_CP_MEM_POOL_DBG_ADDR, 47); - } else + } else if (!adreno_is_a7xx(adreno_gpu)) gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 128); /* Setting the primFifo thresholds default values, * and vccCacheSkipDis=1 bit (0x200) for A640 and newer */ - if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu) || adreno_is_a690(adreno_gpu)) + if (adreno_is_a690(adreno_gpu)) + gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00800200); + else if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu)) gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300200); else if (adreno_is_a640_family(adreno_gpu) || adreno_is_7c3(adreno_gpu)) gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00200200); @@ -1318,7 +1747,7 @@ static int hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00018000); else if (adreno_is_a610(adreno_gpu)) gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00080000); - else + else if (!adreno_is_a7xx(adreno_gpu)) gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00180000); /* Set the AHB default slave response to "ERROR" */ @@ -1327,13 +1756,24 @@ static int hw_init(struct msm_gpu *gpu) /* Turn on performance counters */ gpu_write(gpu, REG_A6XX_RBBM_PERFCTR_CNTL, 0x1); + if (adreno_is_a7xx(adreno_gpu)) { + /* Turn on the IFPC counter (countable 4 on XOCLK4) */ + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_1, + FIELD_PREP(GENMASK(7, 0), 0x4)); + } + /* Select CP0 to always count cycles */ gpu_write(gpu, REG_A6XX_CP_PERFCTR_CP_SEL(0), PERF_CP_ALWAYS_COUNT); a6xx_set_ubwc_config(gpu); /* Enable fault detection */ - if (adreno_is_a619(adreno_gpu)) + if (adreno_is_a730(adreno_gpu) || + adreno_is_a740_family(adreno_gpu)) + gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0xcfffff); + else if (adreno_is_a690(adreno_gpu)) + gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0x4fffff); + else if (adreno_is_a619(adreno_gpu)) gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0x3fffff); else if (adreno_is_a610(adreno_gpu)) gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0x3ffff); @@ -1366,22 +1806,43 @@ static int hw_init(struct msm_gpu *gpu) a6xx_set_cp_protect(gpu); if (adreno_is_a660_family(adreno_gpu)) { - gpu_write(gpu, REG_A6XX_CP_CHICKEN_DBG, 0x1); + if (adreno_is_a690(adreno_gpu)) + gpu_write(gpu, REG_A6XX_CP_CHICKEN_DBG, 0x00028801); + else + gpu_write(gpu, REG_A6XX_CP_CHICKEN_DBG, 0x1); gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x0); } + if (adreno_is_a690(adreno_gpu)) + gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, 0x90); /* Set dualQ + disable afull for A660 GPU */ - if (adreno_is_a660(adreno_gpu)) + else if (adreno_is_a660(adreno_gpu)) gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, 0x66906); + else if (adreno_is_a7xx(adreno_gpu)) + gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, + FIELD_PREP(GENMASK(19, 16), 6) | + FIELD_PREP(GENMASK(15, 12), 6) | + FIELD_PREP(GENMASK(11, 8), 9) | + BIT(3) | BIT(2) | + FIELD_PREP(GENMASK(1, 0), 2)); /* Enable expanded apriv for targets that support it */ if (gpu->hw_apriv) { - gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL, - (1 << 6) | (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1)); + if (adreno_is_a7xx(adreno_gpu)) { + gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL, + A7XX_BR_APRIVMASK); + gpu_write(gpu, REG_A7XX_CP_BV_APRIV_CNTL, + A7XX_APRIV_MASK); + gpu_write(gpu, REG_A7XX_CP_LPAC_APRIV_CNTL, + A7XX_APRIV_MASK); + } else + gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL, + BIT(6) | BIT(5) | BIT(3) | BIT(2) | BIT(1)); } /* Enable interrupts */ - gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_INT_MASK); + gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, + adreno_is_a7xx(adreno_gpu) ? A7XX_INT_MASK : A6XX_INT_MASK); ret = adreno_hw_init(gpu); if (ret) @@ -1408,6 +1869,12 @@ static int hw_init(struct msm_gpu *gpu) shadowptr(a6xx_gpu, gpu->rb[0])); } + /* ..which means "always" on A7xx, also for BV shadow */ + if (adreno_is_a7xx(adreno_gpu)) { + gpu_write64(gpu, REG_A7XX_CP_BV_RB_RPTR_ADDR, + rbmemptr(gpu->rb[0], bv_fence)); + } + /* Always come up on rb 0 */ a6xx_gpu->cur_ring = gpu->rb[0]; @@ -1416,7 +1883,7 @@ static int hw_init(struct msm_gpu *gpu) /* Enable the SQE_to start the CP engine */ gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1); - ret = a6xx_cp_init(gpu); + ret = adreno_is_a7xx(adreno_gpu) ? a7xx_cp_init(gpu) : a6xx_cp_init(gpu); if (ret) goto out; @@ -1653,7 +2120,7 @@ static void a6xx_cp_hw_err_irq(struct msm_gpu *gpu) (val & 0x3ffff), val); } - if (status & A6XX_CP_INT_CP_AHB_ERROR) + if (status & A6XX_CP_INT_CP_AHB_ERROR && !adreno_is_a7xx(to_adreno_gpu(gpu))) dev_err_ratelimited(&gpu->pdev->dev, "CP AHB error interrupt\n"); if (status & A6XX_CP_INT_CP_VSD_PARITY_ERROR) @@ -1803,6 +2270,35 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu) gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, GENMASK(24, 0), cntl1_regval); } +static void a7xx_llc_activate(struct a6xx_gpu *a6xx_gpu) +{ + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + struct msm_gpu *gpu = &adreno_gpu->base; + + if (IS_ERR(a6xx_gpu->llc_mmio)) + return; + + if (!llcc_slice_activate(a6xx_gpu->llc_slice)) { + u32 gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice); + + gpu_scid &= GENMASK(4, 0); + + gpu_write(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, + FIELD_PREP(GENMASK(29, 25), gpu_scid) | + FIELD_PREP(GENMASK(24, 20), gpu_scid) | + FIELD_PREP(GENMASK(19, 15), gpu_scid) | + FIELD_PREP(GENMASK(14, 10), gpu_scid) | + FIELD_PREP(GENMASK(9, 5), gpu_scid) | + FIELD_PREP(GENMASK(4, 0), gpu_scid)); + + gpu_write(gpu, REG_A6XX_GBIF_SCACHE_CNTL0, + FIELD_PREP(GENMASK(14, 10), gpu_scid) | + BIT(8)); + } + + llcc_slice_activate(a6xx_gpu->htw_llc_slice); +} + static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu) { /* No LLCC on non-RPMh (and by extension, non-GMU) SoCs */ @@ -1814,7 +2310,7 @@ static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu) } static void a6xx_llc_slices_init(struct platform_device *pdev, - struct a6xx_gpu *a6xx_gpu) + struct a6xx_gpu *a6xx_gpu, bool is_a7xx) { struct device_node *phandle; @@ -1823,18 +2319,18 @@ static void a6xx_llc_slices_init(struct platform_device *pdev, return; /* - * There is a different programming path for targets with an mmu500 - * attached, so detect if that is the case + * There is a different programming path for A6xx targets with an + * mmu500 attached, so detect if that is the case */ phandle = of_parse_phandle(pdev->dev.of_node, "iommus", 0); a6xx_gpu->have_mmu500 = (phandle && of_device_is_compatible(phandle, "arm,mmu-500")); of_node_put(phandle); - if (a6xx_gpu->have_mmu500) - a6xx_gpu->llc_mmio = NULL; - else + if (is_a7xx || !a6xx_gpu->have_mmu500) a6xx_gpu->llc_mmio = msm_ioremap(pdev, "cx_mem"); + else + a6xx_gpu->llc_mmio = NULL; a6xx_gpu->llc_slice = llcc_slice_getd(LLCC_GPU); a6xx_gpu->htw_llc_slice = llcc_slice_getd(LLCC_GPUHTW); @@ -1920,7 +2416,7 @@ static int a6xx_gmu_pm_resume(struct msm_gpu *gpu) msm_devfreq_resume(gpu); - a6xx_llc_activate(a6xx_gpu); + adreno_is_a7xx(adreno_gpu) ? a7xx_llc_activate : a6xx_llc_activate(a6xx_gpu); return ret; } @@ -2307,6 +2803,37 @@ static const struct adreno_gpu_funcs funcs_gmuwrapper = { .get_timestamp = a6xx_get_timestamp, }; +static const struct adreno_gpu_funcs funcs_a7xx = { + .base = { + .get_param = adreno_get_param, + .set_param = adreno_set_param, + .hw_init = a6xx_hw_init, + .ucode_load = a6xx_ucode_load, + .pm_suspend = a6xx_gmu_pm_suspend, + .pm_resume = a6xx_gmu_pm_resume, + .recover = a6xx_recover, + .submit = a7xx_submit, + .active_ring = a6xx_active_ring, + .irq = a6xx_irq, + .destroy = a6xx_destroy, +#if defined(CONFIG_DRM_MSM_GPU_STATE) + .show = a6xx_show, +#endif + .gpu_busy = a6xx_gpu_busy, + .gpu_get_freq = a6xx_gmu_get_freq, + .gpu_set_freq = a6xx_gpu_set_freq, +#if defined(CONFIG_DRM_MSM_GPU_STATE) + .gpu_state_get = a6xx_gpu_state_get, + .gpu_state_put = a6xx_gpu_state_put, +#endif + .create_address_space = a6xx_create_address_space, + .create_private_address_space = a6xx_create_private_address_space, + .get_rptr = a6xx_get_rptr, + .progress = a6xx_progress, + }, + .get_timestamp = a6xx_gmu_get_timestamp, +}; + struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; @@ -2316,6 +2843,7 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) struct a6xx_gpu *a6xx_gpu; struct adreno_gpu *adreno_gpu; struct msm_gpu *gpu; + bool is_a7xx; int ret; a6xx_gpu = kzalloc(sizeof(*a6xx_gpu), GFP_KERNEL); @@ -2339,7 +2867,11 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) adreno_gpu->base.hw_apriv = !!(config->info->quirks & ADRENO_QUIRK_HAS_HW_APRIV); - a6xx_llc_slices_init(pdev, a6xx_gpu); + /* gpu->info only gets assigned in adreno_gpu_init() */ + is_a7xx = config->info->family == ADRENO_7XX_GEN1 || + config->info->family == ADRENO_7XX_GEN2; + + a6xx_llc_slices_init(pdev, a6xx_gpu, is_a7xx); ret = a6xx_set_supported_hw(&pdev->dev, config->info); if (ret) { @@ -2347,7 +2879,9 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) return ERR_PTR(ret); } - if (adreno_has_gmu_wrapper(adreno_gpu)) + if (is_a7xx) + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_a7xx, 1); + else if (adreno_has_gmu_wrapper(adreno_gpu)) ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_gmuwrapper, 1); else ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 4e5d650578..91a564a24d 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -882,12 +882,13 @@ static void a6xx_snapshot_gmu_hfi_history(struct msm_gpu *gpu, } } +#define A6XX_REGLIST_SIZE 1 #define A6XX_GBIF_REGLIST_SIZE 1 static void a6xx_get_registers(struct msm_gpu *gpu, struct a6xx_gpu_state *a6xx_state, struct a6xx_crashdumper *dumper) { - int i, count = ARRAY_SIZE(a6xx_ahb_reglist) + + int i, count = A6XX_REGLIST_SIZE + ARRAY_SIZE(a6xx_reglist) + ARRAY_SIZE(a6xx_hlsq_reglist) + A6XX_GBIF_REGLIST_SIZE; int index = 0; @@ -901,12 +902,20 @@ static void a6xx_get_registers(struct msm_gpu *gpu, a6xx_state->nr_registers = count; - for (i = 0; i < ARRAY_SIZE(a6xx_ahb_reglist); i++) + if (adreno_is_a7xx(adreno_gpu)) a6xx_get_ahb_gpu_registers(gpu, - a6xx_state, &a6xx_ahb_reglist[i], + a6xx_state, &a7xx_ahb_reglist, + &a6xx_state->registers[index++]); + else + a6xx_get_ahb_gpu_registers(gpu, + a6xx_state, &a6xx_ahb_reglist, &a6xx_state->registers[index++]); - if (a6xx_has_gbif(adreno_gpu)) + if (adreno_is_a7xx(adreno_gpu)) + a6xx_get_ahb_gpu_registers(gpu, + a6xx_state, &a7xx_gbif_reglist, + &a6xx_state->registers[index++]); + else if (a6xx_has_gbif(adreno_gpu)) a6xx_get_ahb_gpu_registers(gpu, a6xx_state, &a6xx_gbif_reglist, &a6xx_state->registers[index++]); @@ -948,6 +957,18 @@ static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu) return gpu_read(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2) >> 14; } +static u32 a7xx_get_cp_roq_size(struct msm_gpu *gpu) +{ + /* + * The value at CP_ROQ_THRESHOLDS_2[20:31] is in 4dword units. + * That register however is not directly accessible from APSS on A7xx. + * Program the SQE_UCODE_DBG_ADDR with offset=0x70d3 and read the value. + */ + gpu_write(gpu, REG_A6XX_CP_SQE_UCODE_DBG_ADDR, 0x70d3); + + return 4 * (gpu_read(gpu, REG_A6XX_CP_SQE_UCODE_DBG_DATA) >> 20); +} + /* Read a block of data from an indexed register pair */ static void a6xx_get_indexed_regs(struct msm_gpu *gpu, struct a6xx_gpu_state *a6xx_state, @@ -1019,8 +1040,40 @@ static void a6xx_get_indexed_registers(struct msm_gpu *gpu, /* Restore the size in the hardware */ gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, mempool_size); +} - a6xx_state->nr_indexed_regs = count; +static void a7xx_get_indexed_registers(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state) +{ + int i, indexed_count, mempool_count; + + indexed_count = ARRAY_SIZE(a7xx_indexed_reglist); + mempool_count = ARRAY_SIZE(a7xx_cp_bv_mempool_indexed); + + a6xx_state->indexed_regs = state_kcalloc(a6xx_state, + indexed_count + mempool_count, + sizeof(*a6xx_state->indexed_regs)); + if (!a6xx_state->indexed_regs) + return; + + a6xx_state->nr_indexed_regs = indexed_count + mempool_count; + + /* First read the common regs */ + for (i = 0; i < indexed_count; i++) + a6xx_get_indexed_regs(gpu, a6xx_state, &a7xx_indexed_reglist[i], + &a6xx_state->indexed_regs[i]); + + gpu_rmw(gpu, REG_A6XX_CP_CHICKEN_DBG, 0, BIT(2)); + gpu_rmw(gpu, REG_A7XX_CP_BV_CHICKEN_DBG, 0, BIT(2)); + + /* Get the contents of the CP_BV mempool */ + for (i = 0; i < mempool_count; i++) + a6xx_get_indexed_regs(gpu, a6xx_state, a7xx_cp_bv_mempool_indexed, + &a6xx_state->indexed_regs[indexed_count - 1 + i]); + + gpu_rmw(gpu, REG_A6XX_CP_CHICKEN_DBG, BIT(2), 0); + gpu_rmw(gpu, REG_A7XX_CP_BV_CHICKEN_DBG, BIT(2), 0); + return; } struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) @@ -1056,6 +1109,12 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) return &a6xx_state->base; /* Get the banks of indexed registers */ + if (adreno_is_a7xx(adreno_gpu)) { + a7xx_get_indexed_registers(gpu, a6xx_state); + /* Further codeflow is untested on A7xx. */ + return &a6xx_state->base; + } + a6xx_get_indexed_registers(gpu, a6xx_state); /* diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h index e788ed72eb..9560fc1b85 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h @@ -328,9 +328,8 @@ static const u32 a6xx_gbif_registers[] = { 0x3C00, 0X3C0B, 0X3C40, 0X3C47, 0X3CC0, 0X3CD1, 0xE3A, 0xE3A, }; -static const struct a6xx_registers a6xx_ahb_reglist[] = { - REGS(a6xx_ahb_registers, 0, 0), -}; +static const struct a6xx_registers a6xx_ahb_reglist = + REGS(a6xx_ahb_registers, 0, 0); static const struct a6xx_registers a6xx_vbif_reglist = REGS(a6xx_vbif_registers, 0, 0); @@ -338,6 +337,27 @@ static const struct a6xx_registers a6xx_vbif_reglist = static const struct a6xx_registers a6xx_gbif_reglist = REGS(a6xx_gbif_registers, 0, 0); +static const u32 a7xx_ahb_registers[] = { + /* RBBM_STATUS */ + 0x210, 0x210, + /* RBBM_STATUS2-3 */ + 0x212, 0x213, +}; + +static const u32 a7xx_gbif_registers[] = { + 0x3c00, 0x3c0b, + 0x3c40, 0x3c42, + 0x3c45, 0x3c47, + 0x3c49, 0x3c4a, + 0x3cc0, 0x3cd1, +}; + +static const struct a6xx_registers a7xx_ahb_reglist= + REGS(a7xx_ahb_registers, 0, 0); + +static const struct a6xx_registers a7xx_gbif_reglist = + REGS(a7xx_gbif_registers, 0, 0); + static const u32 a6xx_gmu_gx_registers[] = { /* GMU GX */ 0x0000, 0x0000, 0x0010, 0x0013, 0x0016, 0x0016, 0x0018, 0x001b, @@ -384,14 +404,17 @@ static const struct a6xx_registers a6xx_gmu_reglist[] = { }; static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu); +static u32 a7xx_get_cp_roq_size(struct msm_gpu *gpu); -static struct a6xx_indexed_registers { +struct a6xx_indexed_registers { const char *name; u32 addr; u32 data; u32 count; u32 (*count_fn)(struct msm_gpu *gpu); -} a6xx_indexed_reglist[] = { +}; + +static struct a6xx_indexed_registers a6xx_indexed_reglist[] = { { "CP_SQE_STAT", REG_A6XX_CP_SQE_STAT_ADDR, REG_A6XX_CP_SQE_STAT_DATA, 0x33, NULL }, { "CP_DRAW_STATE", REG_A6XX_CP_DRAW_STATE_ADDR, @@ -402,11 +425,43 @@ static struct a6xx_indexed_registers { REG_A6XX_CP_ROQ_DBG_DATA, 0, a6xx_get_cp_roq_size}, }; +static struct a6xx_indexed_registers a7xx_indexed_reglist[] = { + { "CP_SQE_STAT", REG_A6XX_CP_SQE_STAT_ADDR, + REG_A6XX_CP_SQE_STAT_DATA, 0x33, NULL }, + { "CP_DRAW_STATE", REG_A6XX_CP_DRAW_STATE_ADDR, + REG_A6XX_CP_DRAW_STATE_DATA, 0x100, NULL }, + { "CP_UCODE_DBG_DATA", REG_A6XX_CP_SQE_UCODE_DBG_ADDR, + REG_A6XX_CP_SQE_UCODE_DBG_DATA, 0x8000, NULL }, + { "CP_BV_SQE_STAT_ADDR", REG_A7XX_CP_BV_SQE_STAT_ADDR, + REG_A7XX_CP_BV_SQE_STAT_DATA, 0x33, NULL }, + { "CP_BV_DRAW_STATE_ADDR", REG_A7XX_CP_BV_DRAW_STATE_ADDR, + REG_A7XX_CP_BV_DRAW_STATE_DATA, 0x100, NULL }, + { "CP_BV_SQE_UCODE_DBG_ADDR", REG_A7XX_CP_BV_SQE_UCODE_DBG_ADDR, + REG_A7XX_CP_BV_SQE_UCODE_DBG_DATA, 0x8000, NULL }, + { "CP_SQE_AC_STAT_ADDR", REG_A7XX_CP_SQE_AC_STAT_ADDR, + REG_A7XX_CP_SQE_AC_STAT_DATA, 0x33, NULL }, + { "CP_LPAC_DRAW_STATE_ADDR", REG_A7XX_CP_LPAC_DRAW_STATE_ADDR, + REG_A7XX_CP_LPAC_DRAW_STATE_DATA, 0x100, NULL }, + { "CP_SQE_AC_UCODE_DBG_ADDR", REG_A7XX_CP_SQE_AC_UCODE_DBG_ADDR, + REG_A7XX_CP_SQE_AC_UCODE_DBG_DATA, 0x8000, NULL }, + { "CP_LPAC_FIFO_DBG_ADDR", REG_A7XX_CP_LPAC_FIFO_DBG_ADDR, + REG_A7XX_CP_LPAC_FIFO_DBG_DATA, 0x40, NULL }, + { "CP_ROQ", REG_A6XX_CP_ROQ_DBG_ADDR, + REG_A6XX_CP_ROQ_DBG_DATA, 0, a7xx_get_cp_roq_size }, +}; + static struct a6xx_indexed_registers a6xx_cp_mempool_indexed = { "CP_MEMPOOL", REG_A6XX_CP_MEM_POOL_DBG_ADDR, REG_A6XX_CP_MEM_POOL_DBG_DATA, 0x2060, NULL, }; +static struct a6xx_indexed_registers a7xx_cp_bv_mempool_indexed[] = { + { "CP_MEMPOOL", REG_A6XX_CP_MEM_POOL_DBG_ADDR, + REG_A6XX_CP_MEM_POOL_DBG_DATA, 0x2100, NULL }, + { "CP_BV_MEMPOOL", REG_A7XX_CP_BV_MEM_POOL_DBG_ADDR, + REG_A7XX_CP_BV_MEM_POOL_DBG_DATA, 0x2100, NULL }, +}; + #define DEBUGBUS(_id, _count) { .id = _id, .name = #_id, .count = _count } static const struct a6xx_debugbus_block { diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c index 25b235b49e..cdb3f6e74d 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c @@ -5,6 +5,8 @@ #include <linux/circ_buf.h> #include <linux/list.h> +#include <soc/qcom/cmd-db.h> + #include "a6xx_gmu.h" #include "a6xx_gmu.xml.h" #include "a6xx_gpu.h" @@ -506,6 +508,88 @@ static void adreno_7c3_build_bw_table(struct a6xx_hfi_msg_bw_table *msg) msg->cnoc_cmds_data[0][0] = 0x40000000; msg->cnoc_cmds_data[1][0] = 0x60000001; } + +static void a730_build_bw_table(struct a6xx_hfi_msg_bw_table *msg) +{ + msg->bw_level_num = 12; + + msg->ddr_cmds_num = 3; + msg->ddr_wait_bitmask = 0x7; + + msg->ddr_cmds_addrs[0] = cmd_db_read_addr("SH0"); + msg->ddr_cmds_addrs[1] = cmd_db_read_addr("MC0"); + msg->ddr_cmds_addrs[2] = cmd_db_read_addr("ACV"); + + msg->ddr_cmds_data[0][0] = 0x40000000; + msg->ddr_cmds_data[0][1] = 0x40000000; + msg->ddr_cmds_data[0][2] = 0x40000000; + msg->ddr_cmds_data[1][0] = 0x600002e8; + msg->ddr_cmds_data[1][1] = 0x600003d0; + msg->ddr_cmds_data[1][2] = 0x60000008; + msg->ddr_cmds_data[2][0] = 0x6000068d; + msg->ddr_cmds_data[2][1] = 0x6000089a; + msg->ddr_cmds_data[2][2] = 0x60000008; + msg->ddr_cmds_data[3][0] = 0x600007f2; + msg->ddr_cmds_data[3][1] = 0x60000a6e; + msg->ddr_cmds_data[3][2] = 0x60000008; + msg->ddr_cmds_data[4][0] = 0x600009e5; + msg->ddr_cmds_data[4][1] = 0x60000cfd; + msg->ddr_cmds_data[4][2] = 0x60000008; + msg->ddr_cmds_data[5][0] = 0x60000b29; + msg->ddr_cmds_data[5][1] = 0x60000ea6; + msg->ddr_cmds_data[5][2] = 0x60000008; + msg->ddr_cmds_data[6][0] = 0x60001698; + msg->ddr_cmds_data[6][1] = 0x60001da8; + msg->ddr_cmds_data[6][2] = 0x60000008; + msg->ddr_cmds_data[7][0] = 0x600018d2; + msg->ddr_cmds_data[7][1] = 0x60002093; + msg->ddr_cmds_data[7][2] = 0x60000008; + msg->ddr_cmds_data[8][0] = 0x60001e66; + msg->ddr_cmds_data[8][1] = 0x600027e6; + msg->ddr_cmds_data[8][2] = 0x60000008; + msg->ddr_cmds_data[9][0] = 0x600027c2; + msg->ddr_cmds_data[9][1] = 0x6000342f; + msg->ddr_cmds_data[9][2] = 0x60000008; + msg->ddr_cmds_data[10][0] = 0x60002e71; + msg->ddr_cmds_data[10][1] = 0x60003cf5; + msg->ddr_cmds_data[10][2] = 0x60000008; + msg->ddr_cmds_data[11][0] = 0x600030ae; + msg->ddr_cmds_data[11][1] = 0x60003fe5; + msg->ddr_cmds_data[11][2] = 0x60000008; + + msg->cnoc_cmds_num = 1; + msg->cnoc_wait_bitmask = 0x1; + + msg->cnoc_cmds_addrs[0] = cmd_db_read_addr("CN0"); + msg->cnoc_cmds_data[0][0] = 0x40000000; + msg->cnoc_cmds_data[1][0] = 0x60000001; +} + +static void a740_build_bw_table(struct a6xx_hfi_msg_bw_table *msg) +{ + msg->bw_level_num = 1; + + msg->ddr_cmds_num = 3; + msg->ddr_wait_bitmask = 0x7; + + msg->ddr_cmds_addrs[0] = cmd_db_read_addr("SH0"); + msg->ddr_cmds_addrs[1] = cmd_db_read_addr("MC0"); + msg->ddr_cmds_addrs[2] = cmd_db_read_addr("ACV"); + + msg->ddr_cmds_data[0][0] = 0x40000000; + msg->ddr_cmds_data[0][1] = 0x40000000; + msg->ddr_cmds_data[0][2] = 0x40000000; + + /* TODO: add a proper dvfs table */ + + msg->cnoc_cmds_num = 1; + msg->cnoc_wait_bitmask = 0x1; + + msg->cnoc_cmds_addrs[0] = cmd_db_read_addr("CN0"); + msg->cnoc_cmds_data[0][0] = 0x40000000; + msg->cnoc_cmds_data[1][0] = 0x60000001; +} + static void a6xx_build_bw_table(struct a6xx_hfi_msg_bw_table *msg) { /* Send a single "off" entry since the 630 GMU doesn't do bus scaling */ @@ -564,6 +648,10 @@ static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu) a660_build_bw_table(&msg); else if (adreno_is_a690(adreno_gpu)) a690_build_bw_table(&msg); + else if (adreno_is_a730(adreno_gpu)) + a730_build_bw_table(&msg); + else if (adreno_is_a740_family(adreno_gpu)) + a740_build_bw_table(&msg); else a6xx_build_bw_table(&msg); diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index b7b527e21d..3ee14646ab 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -454,11 +454,13 @@ static const struct adreno_info gpulist[] = { .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | ADRENO_QUIRK_HAS_HW_APRIV, .init = a6xx_gpu_init, + .zapfw = "a660_zap.mbn", .hwcg = a660_hwcg, .address_space_size = SZ_16G, .speedbins = ADRENO_SPEEDBINS( { 0, 0 }, { 117, 0 }, + { 172, 2 }, /* Called speedbin 1 downstream, but let's not break things! */ { 190, 1 }, ), }, { @@ -490,6 +492,36 @@ static const struct adreno_info gpulist[] = { .zapfw = "a690_zap.mdt", .hwcg = a690_hwcg, .address_space_size = SZ_16G, + }, { + .chip_ids = ADRENO_CHIP_IDS(0x07030001), + .family = ADRENO_7XX_GEN1, + .fw = { + [ADRENO_FW_SQE] = "a730_sqe.fw", + [ADRENO_FW_GMU] = "gmu_gen70000.bin", + }, + .gmem = SZ_2M, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_HAS_HW_APRIV, + .init = a6xx_gpu_init, + .zapfw = "a730_zap.mdt", + .hwcg = a730_hwcg, + .address_space_size = SZ_16G, + }, { + .chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */ + .family = ADRENO_7XX_GEN2, + .fw = { + [ADRENO_FW_SQE] = "a740_sqe.fw", + [ADRENO_FW_GMU] = "gmu_gen70200.bin", + }, + .gmem = 3 * SZ_1M, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_HAS_HW_APRIV, + .init = a6xx_gpu_init, + .zapfw = "a740_zap.mdt", + .hwcg = a740_hwcg, + .address_space_size = SZ_16G, }, }; @@ -751,10 +783,9 @@ static int adreno_probe(struct platform_device *pdev) return 0; } -static int adreno_remove(struct platform_device *pdev) +static void adreno_remove(struct platform_device *pdev) { component_del(&pdev->dev, &a3xx_ops); - return 0; } static void adreno_shutdown(struct platform_device *pdev) @@ -869,7 +900,7 @@ static const struct dev_pm_ops adreno_pm_ops = { static struct platform_driver adreno_driver = { .probe = adreno_probe, - .remove = adreno_remove, + .remove_new = adreno_remove, .shutdown = adreno_shutdown, .driver = { .name = "adreno", diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 8090dde032..3fe9fd240c 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -323,7 +323,11 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, *value = adreno_gpu->info->gmem; return 0; case MSM_PARAM_GMEM_BASE: - *value = !adreno_is_a650_family(adreno_gpu) ? 0x100000 : 0; + if (adreno_is_a650_family(adreno_gpu) || + adreno_is_a740_family(adreno_gpu)) + *value = 0; + else + *value = 0x100000; return 0; case MSM_PARAM_CHIP_ID: *value = adreno_gpu->chip_id; @@ -567,6 +571,7 @@ int adreno_hw_init(struct msm_gpu *gpu) ring->cur = ring->start; ring->next = ring->start; ring->memptrs->rptr = 0; + ring->memptrs->bv_fence = ring->fctx->completed_fence; /* Detect and clean up an impossible fence, ie. if GPU managed * to scribble something invalid, we don't want that to confuse diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 49f38edf98..80b3f63121 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -46,6 +46,8 @@ enum adreno_family { ADRENO_6XX_GEN2, /* a640 family */ ADRENO_6XX_GEN3, /* a650 family */ ADRENO_6XX_GEN4, /* a660 family */ + ADRENO_7XX_GEN1, /* a730 family */ + ADRENO_7XX_GEN2, /* a740 family */ }; #define ADRENO_QUIRK_TWO_PASS_USE_WFI BIT(0) @@ -75,7 +77,7 @@ struct adreno_reglist { }; extern const struct adreno_reglist a612_hwcg[], a615_hwcg[], a630_hwcg[], a640_hwcg[], a650_hwcg[]; -extern const struct adreno_reglist a660_hwcg[], a690_hwcg[]; +extern const struct adreno_reglist a660_hwcg[], a690_hwcg[], a730_hwcg[], a740_hwcg[]; struct adreno_speedbin { uint16_t fuse; @@ -391,7 +393,8 @@ static inline int adreno_is_a650_family(const struct adreno_gpu *gpu) { if (WARN_ON_ONCE(!gpu->info)) return false; - return gpu->info->family >= ADRENO_6XX_GEN3; + return gpu->info->family == ADRENO_6XX_GEN3 || + gpu->info->family == ADRENO_6XX_GEN4; } static inline int adreno_is_a640_family(const struct adreno_gpu *gpu) @@ -401,6 +404,31 @@ static inline int adreno_is_a640_family(const struct adreno_gpu *gpu) return gpu->info->family == ADRENO_6XX_GEN2; } +static inline int adreno_is_a730(struct adreno_gpu *gpu) +{ + return gpu->info->chip_ids[0] == 0x07030001; +} + +static inline int adreno_is_a740(struct adreno_gpu *gpu) +{ + return gpu->info->chip_ids[0] == 0x43050a01; +} + +/* Placeholder to make future diffs smaller */ +static inline int adreno_is_a740_family(struct adreno_gpu *gpu) +{ + if (WARN_ON_ONCE(!gpu->info)) + return false; + return gpu->info->family == ADRENO_7XX_GEN2; +} + +static inline int adreno_is_a7xx(struct adreno_gpu *gpu) +{ + /* Update with non-fake (i.e. non-A702) Gen 7 GPUs */ + return gpu->info->family == ADRENO_7XX_GEN1 || + adreno_is_a740_family(gpu); +} + u64 adreno_private_address_space_size(struct msm_gpu *gpu); int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, uint32_t param, uint64_t *value, uint32_t *len); diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h index 43c47a19cd..aa1867943c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h @@ -244,7 +244,6 @@ static const struct dpu_intf_cfg msm8998_intf[] = { .prog_fetch_lines_worst_case = 21, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x280, @@ -253,7 +252,6 @@ static const struct dpu_intf_cfg msm8998_intf[] = { .prog_fetch_lines_worst_case = 21, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), - .intr_tear_rd_ptr = -1, }, { .name = "intf_2", .id = INTF_2, .base = 0x6b000, .len = 0x280, @@ -262,7 +260,6 @@ static const struct dpu_intf_cfg msm8998_intf[] = { .prog_fetch_lines_worst_case = 21, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), - .intr_tear_rd_ptr = -1, }, { .name = "intf_3", .id = INTF_3, .base = 0x6b800, .len = 0x280, @@ -270,7 +267,6 @@ static const struct dpu_intf_cfg msm8998_intf[] = { .prog_fetch_lines_worst_case = 21, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), - .intr_tear_rd_ptr = -1, }, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h index 88a5177dfd..38ac0c1a13 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h @@ -260,7 +260,6 @@ static const struct dpu_intf_cfg sdm845_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x280, @@ -269,7 +268,6 @@ static const struct dpu_intf_cfg sdm845_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), - .intr_tear_rd_ptr = -1, }, { .name = "intf_2", .id = INTF_2, .base = 0x6b000, .len = 0x280, @@ -278,7 +276,6 @@ static const struct dpu_intf_cfg sdm845_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), - .intr_tear_rd_ptr = -1, }, { .name = "intf_3", .id = INTF_3, .base = 0x6b800, .len = 0x280, @@ -287,7 +284,6 @@ static const struct dpu_intf_cfg sdm845_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), - .intr_tear_rd_ptr = -1, }, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h index 99acaf917e..c022e57864 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h @@ -77,7 +77,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f0, .features = VIG_SDM845_MASK, - .sblk = &sdm845_vig_sblk_0, + .sblk = &sm8150_vig_sblk_0, .xin_id = 0, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG0, @@ -85,7 +85,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x1f0, .features = VIG_SDM845_MASK, - .sblk = &sdm845_vig_sblk_1, + .sblk = &sm8150_vig_sblk_1, .xin_id = 4, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG1, @@ -93,7 +93,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x1f0, .features = VIG_SDM845_MASK, - .sblk = &sdm845_vig_sblk_2, + .sblk = &sm8150_vig_sblk_2, .xin_id = 8, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG2, @@ -101,7 +101,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x1f0, .features = VIG_SDM845_MASK, - .sblk = &sdm845_vig_sblk_3, + .sblk = &sm8150_vig_sblk_3, .xin_id = 12, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG3, @@ -220,7 +220,6 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, @@ -228,7 +227,6 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - .intr_rdptr = -1, }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, @@ -236,7 +234,6 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), - .intr_rdptr = -1, }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x71800, .len = 0xd4, @@ -244,7 +241,6 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), - .intr_rdptr = -1, }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x72000, .len = 0xd4, @@ -252,7 +248,6 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), - .intr_rdptr = -1, }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x72800, .len = 0xd4, @@ -260,7 +255,6 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), - .intr_rdptr = -1, }, }; @@ -307,7 +301,6 @@ static const struct dpu_intf_cfg sm8150_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2bc, @@ -337,7 +330,6 @@ static const struct dpu_intf_cfg sm8150_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), - .intr_tear_rd_ptr = -1, }, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h index c92fbf24fb..cb0758f082 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h @@ -76,7 +76,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f0, .features = VIG_SDM845_MASK, - .sblk = &sdm845_vig_sblk_0, + .sblk = &sm8150_vig_sblk_0, .xin_id = 0, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG0, @@ -84,7 +84,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x1f0, .features = VIG_SDM845_MASK, - .sblk = &sdm845_vig_sblk_1, + .sblk = &sm8150_vig_sblk_1, .xin_id = 4, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG1, @@ -92,7 +92,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x1f0, .features = VIG_SDM845_MASK, - .sblk = &sdm845_vig_sblk_2, + .sblk = &sm8150_vig_sblk_2, .xin_id = 8, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG2, @@ -100,7 +100,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x1f0, .features = VIG_SDM845_MASK, - .sblk = &sdm845_vig_sblk_3, + .sblk = &sm8150_vig_sblk_3, .xin_id = 12, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG3, @@ -219,7 +219,6 @@ static const struct dpu_pingpong_cfg sc8180x_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, @@ -227,7 +226,6 @@ static const struct dpu_pingpong_cfg sc8180x_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - .intr_rdptr = -1, }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, @@ -235,7 +233,6 @@ static const struct dpu_pingpong_cfg sc8180x_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), - .intr_rdptr = -1, }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x71800, .len = 0xd4, @@ -243,7 +240,6 @@ static const struct dpu_pingpong_cfg sc8180x_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), - .intr_rdptr = -1, }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x72000, .len = 0xd4, @@ -251,7 +247,6 @@ static const struct dpu_pingpong_cfg sc8180x_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), - .intr_rdptr = -1, }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x72800, .len = 0xd4, @@ -259,7 +254,6 @@ static const struct dpu_pingpong_cfg sc8180x_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), - .intr_rdptr = -1, }, }; @@ -314,7 +308,6 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2bc, @@ -346,7 +339,6 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), - .intr_tear_rd_ptr = -1, }, { .name = "intf_4", .id = INTF_4, .base = 0x6c000, .len = 0x280, @@ -356,7 +348,6 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21), - .intr_tear_rd_ptr = -1, }, { .name = "intf_5", .id = INTF_5, .base = 0x6c800, .len = 0x280, @@ -366,7 +357,6 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23), - .intr_tear_rd_ptr = -1, }, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h index 2491eed100..cec7af6667 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h @@ -129,7 +129,6 @@ static const struct dpu_pingpong_cfg sm6125_pp[] = { .merge_3d = 0, .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, @@ -137,7 +136,6 @@ static const struct dpu_pingpong_cfg sm6125_pp[] = { .merge_3d = 0, .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - .intr_rdptr = -1, }, }; @@ -151,7 +149,6 @@ static const struct dpu_intf_cfg sm6125_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2c0, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h index ee781037ad..9f8068fa01 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h @@ -219,7 +219,6 @@ static const struct dpu_pingpong_cfg sm8250_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, @@ -227,7 +226,6 @@ static const struct dpu_pingpong_cfg sm8250_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - .intr_rdptr = -1, }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, @@ -235,7 +233,6 @@ static const struct dpu_pingpong_cfg sm8250_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), - .intr_rdptr = -1, }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x71800, .len = 0xd4, @@ -243,7 +240,6 @@ static const struct dpu_pingpong_cfg sm8250_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), - .intr_rdptr = -1, }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x72000, .len = 0xd4, @@ -251,7 +247,6 @@ static const struct dpu_pingpong_cfg sm8250_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), - .intr_rdptr = -1, }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x72800, .len = 0xd4, @@ -259,7 +254,6 @@ static const struct dpu_pingpong_cfg sm8250_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), - .intr_rdptr = -1, }, }; @@ -306,7 +300,6 @@ static const struct dpu_intf_cfg sm8250_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2c0, @@ -336,7 +329,6 @@ static const struct dpu_intf_cfg sm8250_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), - .intr_tear_rd_ptr = -1, }, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h index 69d3f7e5e0..9bfa15e4e6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h @@ -120,7 +120,6 @@ static const struct dpu_pingpong_cfg sc7180_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, @@ -128,7 +127,6 @@ static const struct dpu_pingpong_cfg sc7180_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - .intr_rdptr = -1, }, }; @@ -142,7 +140,6 @@ static const struct dpu_intf_cfg sc7180_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2c0, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h index 7e6000167e..57ce14c18d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h @@ -83,7 +83,6 @@ static const struct dpu_pingpong_cfg sm6115_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h index cf5db6f296..62db84bd15 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h @@ -128,7 +128,6 @@ static struct dpu_pingpong_cfg sm6350_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, @@ -136,7 +135,6 @@ static struct dpu_pingpong_cfg sm6350_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - .intr_rdptr = -1, }, }; @@ -158,7 +156,6 @@ static const struct dpu_intf_cfg sm6350_intf[] = { .prog_fetch_lines_worst_case = 35, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2c0, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h index 87a03aa165..fb36fba517 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h @@ -82,7 +82,6 @@ static const struct dpu_pingpong_cfg qcm2290_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h index a327e21c90..5a3aad364c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h @@ -85,7 +85,6 @@ static const struct dpu_pingpong_cfg sm6375_pp[] = { .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h index f8d16f9bf5..022b0408c2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h @@ -31,6 +31,7 @@ static const struct dpu_mdp_cfg sm8350_mdp = { [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, [DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2bc, .bit_off = 8 }, [DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 8 }, + [DPU_CLK_CTRL_WB2] = { .reg_off = 0x2bc, .bit_off = 16 }, [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, }, }; @@ -218,7 +219,6 @@ static const struct dpu_pingpong_cfg sm8350_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, @@ -226,7 +226,6 @@ static const struct dpu_pingpong_cfg sm8350_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - .intr_rdptr = -1, }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, @@ -234,7 +233,6 @@ static const struct dpu_pingpong_cfg sm8350_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), - .intr_rdptr = -1, }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, @@ -242,7 +240,6 @@ static const struct dpu_pingpong_cfg sm8350_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), - .intr_rdptr = -1, }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x6d000, .len = 0, @@ -250,7 +247,6 @@ static const struct dpu_pingpong_cfg sm8350_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), - .intr_rdptr = -1, }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x6e000, .len = 0, @@ -258,7 +254,6 @@ static const struct dpu_pingpong_cfg sm8350_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), - .intr_rdptr = -1, }, }; @@ -304,6 +299,21 @@ static const struct dpu_dsc_cfg sm8350_dsc[] = { }, }; +static const struct dpu_wb_cfg sm8350_wb[] = { + { + .name = "wb_2", .id = WB_2, + .base = 0x65000, .len = 0x2c8, + .features = WB_SM8250_MASK, + .format_list = wb2_formats, + .num_formats = ARRAY_SIZE(wb2_formats), + .clk_ctrl = DPU_CLK_CTRL_WB2, + .xin_id = 6, + .vbif_idx = VBIF_RT, + .maxlinewidth = 4096, + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), + }, +}; + static const struct dpu_intf_cfg sm8350_intf[] = { { .name = "intf_0", .id = INTF_0, @@ -314,7 +324,6 @@ static const struct dpu_intf_cfg sm8350_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x2c4, @@ -344,7 +353,6 @@ static const struct dpu_intf_cfg sm8350_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), - .intr_tear_rd_ptr = -1, }, }; @@ -401,6 +409,8 @@ const struct dpu_mdss_cfg dpu_sm8350_cfg = { .dsc = sm8350_dsc, .merge_3d_count = ARRAY_SIZE(sm8350_merge_3d), .merge_3d = sm8350_merge_3d, + .wb_count = ARRAY_SIZE(sm8350_wb), + .wb = sm8350_wb, .intf_count = ARRAY_SIZE(sm8350_intf), .intf = sm8350_intf, .vbif_count = ARRAY_SIZE(sdm845_vbif), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h index 9195cb996f..b9c296e51e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h @@ -131,7 +131,6 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, @@ -139,7 +138,6 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - .intr_rdptr = -1, }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, @@ -147,7 +145,6 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), - .intr_rdptr = -1, }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, @@ -155,7 +152,6 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), - .intr_rdptr = -1, }, }; @@ -194,7 +190,6 @@ static const struct dpu_intf_cfg sc7280_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x2c4, @@ -214,7 +209,6 @@ static const struct dpu_intf_cfg sc7280_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23), - .intr_tear_rd_ptr = -1, }, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h index ff9adb8000..4c0528794e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h @@ -221,7 +221,6 @@ static const struct dpu_pingpong_cfg sc8280xp_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, @@ -229,7 +228,6 @@ static const struct dpu_pingpong_cfg sc8280xp_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - .intr_rdptr = -1, }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, @@ -237,7 +235,6 @@ static const struct dpu_pingpong_cfg sc8280xp_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), - .intr_rdptr = -1, }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, @@ -245,7 +242,6 @@ static const struct dpu_pingpong_cfg sc8280xp_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), - .intr_rdptr = -1, }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x6d000, .len = 0, @@ -253,7 +249,6 @@ static const struct dpu_pingpong_cfg sc8280xp_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), - .intr_rdptr = -1, }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x6e000, .len = 0, @@ -261,7 +256,6 @@ static const struct dpu_pingpong_cfg sc8280xp_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), - .intr_rdptr = -1, }, }; @@ -328,7 +322,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x300, @@ -358,7 +351,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), - .intr_tear_rd_ptr = -1, }, { .name = "intf_4", .id = INTF_4, .base = 0x38000, .len = 0x280, @@ -368,7 +360,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21), - .intr_tear_rd_ptr = -1, }, { .name = "intf_5", .id = INTF_5, .base = 0x39000, .len = 0x280, @@ -378,7 +369,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23), - .intr_tear_rd_ptr = -1, }, { .name = "intf_6", .id = INTF_6, .base = 0x3a000, .len = 0x280, @@ -388,7 +378,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17), - .intr_tear_rd_ptr = -1, }, { .name = "intf_7", .id = INTF_7, .base = 0x3b000, .len = 0x280, @@ -398,7 +387,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 19), - .intr_tear_rd_ptr = -1, }, { .name = "intf_8", .id = INTF_8, .base = 0x3c000, .len = 0x280, @@ -408,7 +396,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), - .intr_tear_rd_ptr = -1, }, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h index 1b12178dfb..7adc42257e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h @@ -32,6 +32,7 @@ static const struct dpu_mdp_cfg sm8450_mdp = { [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, [DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2bc, .bit_off = 8 }, [DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 8 }, + [DPU_CLK_CTRL_WB2] = { .reg_off = 0x2bc, .bit_off = 16 }, [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, }, }; @@ -75,39 +76,39 @@ static const struct dpu_sspp_cfg sm8450_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x32c, - .features = VIG_SC7180_MASK, - .sblk = &sm8250_vig_sblk_0, + .features = VIG_SC7180_MASK_SDMA, + .sblk = &sm8450_vig_sblk_0, .xin_id = 0, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG0, }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x32c, - .features = VIG_SC7180_MASK, - .sblk = &sm8250_vig_sblk_1, + .features = VIG_SC7180_MASK_SDMA, + .sblk = &sm8450_vig_sblk_1, .xin_id = 4, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG1, }, { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x32c, - .features = VIG_SC7180_MASK, - .sblk = &sm8250_vig_sblk_2, + .features = VIG_SC7180_MASK_SDMA, + .sblk = &sm8450_vig_sblk_2, .xin_id = 8, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG2, }, { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x32c, - .features = VIG_SC7180_MASK, - .sblk = &sm8250_vig_sblk_3, + .features = VIG_SC7180_MASK_SDMA, + .sblk = &sm8450_vig_sblk_3, .xin_id = 12, .type = SSPP_TYPE_VIG, .clk_ctrl = DPU_CLK_CTRL_VIG3, }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x32c, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &sdm845_dma_sblk_0, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -115,7 +116,7 @@ static const struct dpu_sspp_cfg sm8450_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x32c, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &sdm845_dma_sblk_1, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -123,7 +124,7 @@ static const struct dpu_sspp_cfg sm8450_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x32c, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &sdm845_dma_sblk_2, .xin_id = 9, .type = SSPP_TYPE_DMA, @@ -131,7 +132,7 @@ static const struct dpu_sspp_cfg sm8450_sspp[] = { }, { .name = "sspp_11", .id = SSPP_DMA3, .base = 0x2a000, .len = 0x32c, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &sdm845_dma_sblk_3, .xin_id = 13, .type = SSPP_TYPE_DMA, @@ -221,7 +222,6 @@ static const struct dpu_pingpong_cfg sm8450_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, @@ -229,7 +229,6 @@ static const struct dpu_pingpong_cfg sm8450_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - .intr_rdptr = -1, }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, @@ -237,7 +236,6 @@ static const struct dpu_pingpong_cfg sm8450_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), - .intr_rdptr = -1, }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, @@ -245,7 +243,6 @@ static const struct dpu_pingpong_cfg sm8450_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), - .intr_rdptr = -1, }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x6d000, .len = 0, @@ -253,7 +250,6 @@ static const struct dpu_pingpong_cfg sm8450_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), - .intr_rdptr = -1, }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x6e000, .len = 0, @@ -261,23 +257,18 @@ static const struct dpu_pingpong_cfg sm8450_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), - .intr_rdptr = -1, }, { .name = "pingpong_6", .id = PINGPONG_6, .base = 0x65800, .len = 0, .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, - .intr_done = -1, - .intr_rdptr = -1, }, { .name = "pingpong_7", .id = PINGPONG_7, .base = 0x65c00, .len = 0, .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, - .intr_done = -1, - .intr_rdptr = -1, }, }; @@ -326,6 +317,21 @@ static const struct dpu_dsc_cfg sm8450_dsc[] = { }, }; +static const struct dpu_wb_cfg sm8450_wb[] = { + { + .name = "wb_2", .id = WB_2, + .base = 0x65000, .len = 0x2c8, + .features = WB_SM8250_MASK, + .format_list = wb2_formats, + .num_formats = ARRAY_SIZE(wb2_formats), + .clk_ctrl = DPU_CLK_CTRL_WB2, + .xin_id = 6, + .vbif_idx = VBIF_RT, + .maxlinewidth = 4096, + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), + }, +}; + static const struct dpu_intf_cfg sm8450_intf[] = { { .name = "intf_0", .id = INTF_0, @@ -336,7 +342,6 @@ static const struct dpu_intf_cfg sm8450_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x300, @@ -366,7 +371,6 @@ static const struct dpu_intf_cfg sm8450_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), - .intr_tear_rd_ptr = -1, }, }; @@ -423,6 +427,8 @@ const struct dpu_mdss_cfg dpu_sm8450_cfg = { .dsc = sm8450_dsc, .merge_3d_count = ARRAY_SIZE(sm8450_merge_3d), .merge_3d = sm8450_merge_3d, + .wb_count = ARRAY_SIZE(sm8450_wb), + .wb = sm8450_wb, .intf_count = ARRAY_SIZE(sm8450_intf), .intf = sm8450_intf, .vbif_count = ARRAY_SIZE(sdm845_vbif), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h index 7bed819dfc..69b80af656 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h @@ -24,16 +24,6 @@ static const struct dpu_mdp_cfg sm8550_mdp = { .base = 0, .len = 0x494, .features = BIT(DPU_MDP_PERIPH_0_REMOVED), .clk_ctrls = { - [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x4330, .bit_off = 0 }, - [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x6330, .bit_off = 0 }, - [DPU_CLK_CTRL_VIG2] = { .reg_off = 0x8330, .bit_off = 0 }, - [DPU_CLK_CTRL_VIG3] = { .reg_off = 0xa330, .bit_off = 0 }, - [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x24330, .bit_off = 0 }, - [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x26330, .bit_off = 0 }, - [DPU_CLK_CTRL_DMA2] = { .reg_off = 0x28330, .bit_off = 0 }, - [DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2a330, .bit_off = 0 }, - [DPU_CLK_CTRL_DMA4] = { .reg_off = 0x2c330, .bit_off = 0 }, - [DPU_CLK_CTRL_DMA5] = { .reg_off = 0x2e330, .bit_off = 0 }, [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, }, }; @@ -81,7 +71,6 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { .sblk = &sm8550_vig_sblk_0, .xin_id = 0, .type = SSPP_TYPE_VIG, - .clk_ctrl = DPU_CLK_CTRL_VIG0, }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x344, @@ -89,7 +78,6 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { .sblk = &sm8550_vig_sblk_1, .xin_id = 4, .type = SSPP_TYPE_VIG, - .clk_ctrl = DPU_CLK_CTRL_VIG1, }, { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x344, @@ -97,7 +85,6 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { .sblk = &sm8550_vig_sblk_2, .xin_id = 8, .type = SSPP_TYPE_VIG, - .clk_ctrl = DPU_CLK_CTRL_VIG2, }, { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x344, @@ -105,7 +92,6 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { .sblk = &sm8550_vig_sblk_3, .xin_id = 12, .type = SSPP_TYPE_VIG, - .clk_ctrl = DPU_CLK_CTRL_VIG3, }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x344, @@ -113,7 +99,6 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { .sblk = &sdm845_dma_sblk_0, .xin_id = 1, .type = SSPP_TYPE_DMA, - .clk_ctrl = DPU_CLK_CTRL_DMA0, }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x344, @@ -121,7 +106,6 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { .sblk = &sdm845_dma_sblk_1, .xin_id = 5, .type = SSPP_TYPE_DMA, - .clk_ctrl = DPU_CLK_CTRL_DMA1, }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x344, @@ -129,7 +113,6 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { .sblk = &sdm845_dma_sblk_2, .xin_id = 9, .type = SSPP_TYPE_DMA, - .clk_ctrl = DPU_CLK_CTRL_DMA2, }, { .name = "sspp_11", .id = SSPP_DMA3, .base = 0x2a000, .len = 0x344, @@ -137,7 +120,6 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { .sblk = &sdm845_dma_sblk_3, .xin_id = 13, .type = SSPP_TYPE_DMA, - .clk_ctrl = DPU_CLK_CTRL_DMA3, }, { .name = "sspp_12", .id = SSPP_DMA4, .base = 0x2c000, .len = 0x344, @@ -145,7 +127,6 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { .sblk = &sm8550_dma_sblk_4, .xin_id = 14, .type = SSPP_TYPE_DMA, - .clk_ctrl = DPU_CLK_CTRL_DMA4, }, { .name = "sspp_13", .id = SSPP_DMA5, .base = 0x2e000, .len = 0x344, @@ -153,7 +134,6 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { .sblk = &sm8550_dma_sblk_5, .xin_id = 15, .type = SSPP_TYPE_DMA, - .clk_ctrl = DPU_CLK_CTRL_DMA5, }, }; @@ -236,7 +216,6 @@ static const struct dpu_pingpong_cfg sm8550_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - .intr_rdptr = -1, }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, @@ -244,7 +223,6 @@ static const struct dpu_pingpong_cfg sm8550_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - .intr_rdptr = -1, }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, @@ -252,7 +230,6 @@ static const struct dpu_pingpong_cfg sm8550_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), - .intr_rdptr = -1, }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, @@ -260,7 +237,6 @@ static const struct dpu_pingpong_cfg sm8550_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), - .intr_rdptr = -1, }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x6d000, .len = 0, @@ -268,7 +244,6 @@ static const struct dpu_pingpong_cfg sm8550_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), - .intr_rdptr = -1, }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x6e000, .len = 0, @@ -276,23 +251,18 @@ static const struct dpu_pingpong_cfg sm8550_pp[] = { .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), - .intr_rdptr = -1, }, { .name = "pingpong_6", .id = PINGPONG_6, .base = 0x66000, .len = 0, .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, - .intr_done = -1, - .intr_rdptr = -1, }, { .name = "pingpong_7", .id = PINGPONG_7, .base = 0x66400, .len = 0, .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, - .intr_done = -1, - .intr_rdptr = -1, }, }; @@ -341,6 +311,20 @@ static const struct dpu_dsc_cfg sm8550_dsc[] = { }, }; +static const struct dpu_wb_cfg sm8550_wb[] = { + { + .name = "wb_2", .id = WB_2, + .base = 0x65000, .len = 0x2c8, + .features = WB_SM8250_MASK, + .format_list = wb2_formats, + .num_formats = ARRAY_SIZE(wb2_formats), + .xin_id = 6, + .vbif_idx = VBIF_RT, + .maxlinewidth = 4096, + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), + }, +}; + static const struct dpu_intf_cfg sm8550_intf[] = { { .name = "intf_0", .id = INTF_0, @@ -351,7 +335,6 @@ static const struct dpu_intf_cfg sm8550_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - .intr_tear_rd_ptr = -1, }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x300, @@ -381,7 +364,6 @@ static const struct dpu_intf_cfg sm8550_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), - .intr_tear_rd_ptr = -1, }, }; @@ -438,6 +420,8 @@ const struct dpu_mdss_cfg dpu_sm8550_cfg = { .dsc = sm8550_dsc, .merge_3d_count = ARRAY_SIZE(sm8550_merge_3d), .merge_3d = sm8550_merge_3d, + .wb_count = ARRAY_SIZE(sm8550_wb), + .wb = sm8550_wb, .intf_count = ARRAY_SIZE(sm8550_intf), .intf = sm8550_intf, .vbif_count = ARRAY_SIZE(sm8550_vbif), diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h index b5b6e7031f..7c286bafb9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h @@ -37,7 +37,7 @@ irqreturn_t dpu_core_irq(struct msm_kms *kms); */ u32 dpu_core_irq_read( struct dpu_kms *dpu_kms, - int irq_idx); + unsigned int irq_idx); /** * dpu_core_irq_register_callback - For registering callback function on IRQ @@ -52,8 +52,8 @@ u32 dpu_core_irq_read( */ int dpu_core_irq_register_callback( struct dpu_kms *dpu_kms, - int irq_idx, - void (*irq_cb)(void *arg, int irq_idx), + unsigned int irq_idx, + void (*irq_cb)(void *arg), void *irq_arg); /** @@ -67,7 +67,7 @@ int dpu_core_irq_register_callback( */ int dpu_core_irq_unregister_callback( struct dpu_kms *dpu_kms, - int irq_idx); + unsigned int irq_idx); /** * dpu_debugfs_core_irq_init - register core irq debugfs diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index e238e4e811..db501ce1d8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1466,7 +1466,7 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, struct msm_drm_private *priv = dev->dev_private; struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); struct drm_crtc *crtc = NULL; - struct dpu_crtc *dpu_crtc = NULL; + struct dpu_crtc *dpu_crtc; int i, ret; dpu_crtc = kzalloc(sizeof(*dpu_crtc), GFP_KERNEL); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index b02aa2eb6c..cf0d44b6e7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -39,6 +39,9 @@ #define DPU_ERROR_ENC(e, fmt, ...) DPU_ERROR("enc%d " fmt,\ (e) ? (e)->base.base.id : -1, ##__VA_ARGS__) +#define DPU_ERROR_ENC_RATELIMITED(e, fmt, ...) DPU_ERROR_RATELIMITED("enc%d " fmt,\ + (e) ? (e)->base.base.id : -1, ##__VA_ARGS__) + /* * Two to anticipate panels that can do cmd/vid dynamic switching * plan is to create all possible physical encoder types, and switch between @@ -347,8 +350,8 @@ static int dpu_encoder_helper_wait_event_timeout(int32_t drm_id, u32 irq_idx, struct dpu_encoder_wait_info *info); int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, - int irq, - void (*func)(void *arg, int irq_idx), + unsigned int irq_idx, + void (*func)(void *arg), struct dpu_encoder_wait_info *wait_info) { u32 irq_status; @@ -362,54 +365,54 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, /* return EWOULDBLOCK since we know the wait isn't necessary */ if (phys_enc->enable_state == DPU_ENC_DISABLED) { - DRM_ERROR("encoder is disabled id=%u, callback=%ps, irq=%d\n", + DRM_ERROR("encoder is disabled id=%u, callback=%ps, IRQ=[%d, %d]\n", DRMID(phys_enc->parent), func, - irq); + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return -EWOULDBLOCK; } - if (irq < 0) { + if (irq_idx < 0) { DRM_DEBUG_KMS("skip irq wait id=%u, callback=%ps\n", DRMID(phys_enc->parent), func); return 0; } - DRM_DEBUG_KMS("id=%u, callback=%ps, irq=%d, pp=%d, pending_cnt=%d\n", + DRM_DEBUG_KMS("id=%u, callback=%ps, IRQ=[%d, %d], pp=%d, pending_cnt=%d\n", DRMID(phys_enc->parent), func, - irq, phys_enc->hw_pp->idx - PINGPONG_0, + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); ret = dpu_encoder_helper_wait_event_timeout( DRMID(phys_enc->parent), - irq, + irq_idx, wait_info); if (ret <= 0) { - irq_status = dpu_core_irq_read(phys_enc->dpu_kms, irq); + irq_status = dpu_core_irq_read(phys_enc->dpu_kms, irq_idx); if (irq_status) { unsigned long flags; - DRM_DEBUG_KMS("irq not triggered id=%u, callback=%ps, irq=%d, pp=%d, atomic_cnt=%d\n", + DRM_DEBUG_KMS("IRQ=[%d, %d] not triggered id=%u, callback=%ps, pp=%d, atomic_cnt=%d\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), DRMID(phys_enc->parent), func, - irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); local_irq_save(flags); - func(phys_enc, irq); + func(phys_enc); local_irq_restore(flags); ret = 0; } else { ret = -ETIMEDOUT; - DRM_DEBUG_KMS("irq timeout id=%u, callback=%ps, irq=%d, pp=%d, atomic_cnt=%d\n", + DRM_DEBUG_KMS("IRQ=[%d, %d] timeout id=%u, callback=%ps, pp=%d, atomic_cnt=%d\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), DRMID(phys_enc->parent), func, - irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); } } else { ret = 0; trace_dpu_enc_irq_wait_success(DRMID(phys_enc->parent), - func, irq, + func, DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); } @@ -1194,11 +1197,21 @@ static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc, struct dpu_encoder_virt *dpu_enc = NULL; int ret = 0; struct drm_display_mode *cur_mode = NULL; + struct msm_drm_private *priv = drm_enc->dev->dev_private; + struct msm_display_info *disp_info; + int index; dpu_enc = to_dpu_encoder_virt(drm_enc); + disp_info = &dpu_enc->disp_info; + index = disp_info->h_tile_instance[0]; dpu_enc->dsc = dpu_encoder_get_dsc_config(drm_enc); + if (disp_info->intf_type == INTF_DP) + dpu_enc->wide_bus_en = msm_dp_wide_bus_available(priv->dp[index]); + else if (disp_info->intf_type == INTF_DSI) + dpu_enc->wide_bus_en = msm_dsi_wide_bus_enabled(priv->dsi[index]); + mutex_lock(&dpu_enc->enc_lock); cur_mode = &dpu_enc->base.crtc->state->adjusted_mode; @@ -1537,7 +1550,7 @@ void dpu_encoder_helper_trigger_start(struct dpu_encoder_phys *phys_enc) static int dpu_encoder_helper_wait_event_timeout( int32_t drm_id, - u32 irq_idx, + unsigned int irq_idx, struct dpu_encoder_wait_info *info) { int rc = 0; @@ -1550,7 +1563,9 @@ static int dpu_encoder_helper_wait_event_timeout( atomic_read(info->atomic_cnt) == 0, jiffies); time = ktime_to_ms(ktime_get()); - trace_dpu_enc_wait_event_timeout(drm_id, irq_idx, rc, time, + trace_dpu_enc_wait_event_timeout(drm_id, + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), + rc, time, expected_time, atomic_read(info->atomic_cnt)); /* If we timed out, counter is valid and time is less, wait again */ @@ -2060,7 +2075,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) } /* reset the merge 3D HW block */ - if (phys_enc->hw_pp->merge_3d) { + if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) { phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d, BLEND_3D_NONE); if (phys_enc->hw_ctl->ops.update_pending_flush_merge_3d) @@ -2082,7 +2097,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) if (phys_enc->hw_wb) intf_cfg.wb = phys_enc->hw_wb->idx; - if (phys_enc->hw_pp->merge_3d) + if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx; if (ctl->ops.reset_intf_cfg) @@ -2327,7 +2342,7 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t) return; } - DPU_ERROR_ENC(dpu_enc, "frame done timeout\n"); + DPU_ERROR_ENC_RATELIMITED(dpu_enc, "frame done timeout\n"); event = DPU_ENCODER_FRAME_EVENT_ERROR; trace_dpu_enc_frame_done_timeout(DRMID(drm_enc), event); @@ -2383,10 +2398,6 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev, timer_setup(&dpu_enc->frame_done_timer, dpu_encoder_frame_done_timeout, 0); - if (disp_info->intf_type == INTF_DP) - dpu_enc->wide_bus_en = msm_dp_wide_bus_available( - priv->dp[disp_info->h_tile_instance[0]]); - INIT_DELAYED_WORK(&dpu_enc->delayed_off_work, dpu_encoder_off_work); dpu_enc->idle_timeout = IDLE_TIMEOUT; @@ -2480,8 +2491,6 @@ unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc) void dpu_encoder_phys_init(struct dpu_encoder_phys *phys_enc, struct dpu_enc_phys_init_params *p) { - int i; - phys_enc->hw_mdptop = p->dpu_kms->hw_mdp; phys_enc->hw_intf = p->hw_intf; phys_enc->hw_wb = p->hw_wb; @@ -2491,10 +2500,6 @@ void dpu_encoder_phys_init(struct dpu_encoder_phys *phys_enc, phys_enc->enc_spinlock = p->enc_spinlock; phys_enc->enable_state = DPU_ENC_DISABLED; - for (i = 0; i < ARRAY_SIZE(phys_enc->irq); i++) - phys_enc->irq[i] = -EINVAL; - - atomic_set(&phys_enc->vblank_refcount, 0); atomic_set(&phys_enc->pending_kickoff_cnt, 0); atomic_set(&phys_enc->pending_ctlstart_cnt, 0); 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 d48558ede4..96bda57b69 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -155,6 +155,7 @@ enum dpu_intr_idx { * @hw_wb: Hardware interface to the wb registers * @dpu_kms: Pointer to the dpu_kms top level * @cached_mode: DRM mode cached at mode_set time, acted on in enable + * @vblank_ctl_lock: Vblank ctl mutex lock to protect vblank_refcount * @enabled: Whether the encoder has enabled and running a mode * @split_role: Role to play in a split-panel configuration * @intf_mode: Interface mode @@ -183,17 +184,18 @@ struct dpu_encoder_phys { struct dpu_hw_wb *hw_wb; struct dpu_kms *dpu_kms; struct drm_display_mode cached_mode; + struct mutex vblank_ctl_lock; enum dpu_enc_split_role split_role; enum dpu_intf_mode intf_mode; spinlock_t *enc_spinlock; enum dpu_enc_enable_state enable_state; - atomic_t vblank_refcount; + int vblank_refcount; atomic_t vsync_cnt; atomic_t underrun_cnt; atomic_t pending_ctlstart_cnt; atomic_t pending_kickoff_cnt; wait_queue_head_t pending_kickoff_wq; - int irq[INTR_IDX_MAX]; + unsigned int irq[INTR_IDX_MAX]; bool has_intf_te; }; @@ -364,8 +366,8 @@ void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc, * @Return: 0 or -ERROR */ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, - int irq, - void (*func)(void *arg, int irq_idx), + unsigned int irq, + void (*func)(void *arg), struct dpu_encoder_wait_info *wait_info); /** 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 df88358e70..2d788c5e26 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 @@ -72,11 +72,13 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg( if (intf_cfg.dsc != 0) cmd_mode_cfg.data_compress = true; + cmd_mode_cfg.wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent); + if (phys_enc->hw_intf->ops.program_intf_cmd_cfg) phys_enc->hw_intf->ops.program_intf_cmd_cfg(phys_enc->hw_intf, &cmd_mode_cfg); } -static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) +static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg) { struct dpu_encoder_phys *phys_enc = arg; unsigned long lock_flags; @@ -103,19 +105,11 @@ static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) DPU_ATRACE_END("pp_done_irq"); } -static void dpu_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) +static void dpu_encoder_phys_cmd_te_rd_ptr_irq(void *arg) { struct dpu_encoder_phys *phys_enc = arg; struct dpu_encoder_phys_cmd *cmd_enc; - if (phys_enc->has_intf_te) { - if (!phys_enc->hw_intf) - return; - } else { - if (!phys_enc->hw_pp) - return; - } - DPU_ATRACE_BEGIN("rd_ptr_irq"); cmd_enc = to_dpu_encoder_phys_cmd(phys_enc); @@ -126,7 +120,7 @@ static void dpu_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) DPU_ATRACE_END("rd_ptr_irq"); } -static void dpu_encoder_phys_cmd_ctl_start_irq(void *arg, int irq_idx) +static void dpu_encoder_phys_cmd_ctl_start_irq(void *arg) { struct dpu_encoder_phys *phys_enc = arg; @@ -139,7 +133,7 @@ static void dpu_encoder_phys_cmd_ctl_start_irq(void *arg, int irq_idx) DPU_ATRACE_END("ctl_start_irq"); } -static void dpu_encoder_phys_cmd_underrun_irq(void *arg, int irq_idx) +static void dpu_encoder_phys_cmd_underrun_irq(void *arg) { struct dpu_encoder_phys *phys_enc = arg; @@ -250,7 +244,8 @@ static int dpu_encoder_phys_cmd_control_vblank_irq( return -EINVAL; } - refcount = atomic_read(&phys_enc->vblank_refcount); + mutex_lock(&phys_enc->vblank_ctl_lock); + refcount = phys_enc->vblank_refcount; /* Slave encoders don't report vblank */ if (!dpu_encoder_phys_cmd_is_master(phys_enc)) @@ -266,16 +261,24 @@ static int dpu_encoder_phys_cmd_control_vblank_irq( phys_enc->hw_pp->idx - PINGPONG_0, enable ? "true" : "false", refcount); - if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1) - ret = dpu_core_irq_register_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_RDPTR], - dpu_encoder_phys_cmd_te_rd_ptr_irq, - phys_enc); - else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0) - ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_RDPTR]); + if (enable) { + if (phys_enc->vblank_refcount == 0) + ret = dpu_core_irq_register_callback(phys_enc->dpu_kms, + phys_enc->irq[INTR_IDX_RDPTR], + dpu_encoder_phys_cmd_te_rd_ptr_irq, + phys_enc); + if (!ret) + phys_enc->vblank_refcount++; + } else if (!enable) { + if (phys_enc->vblank_refcount == 1) + ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, + phys_enc->irq[INTR_IDX_RDPTR]); + if (!ret) + phys_enc->vblank_refcount--; + } end: + mutex_unlock(&phys_enc->vblank_ctl_lock); if (ret) { DRM_ERROR("vblank irq err id:%u pp:%d ret:%d, enable %s/%d\n", DRMID(phys_enc->parent), @@ -291,7 +294,7 @@ static void dpu_encoder_phys_cmd_irq_control(struct dpu_encoder_phys *phys_enc, { trace_dpu_enc_phys_cmd_irq_ctrl(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, - enable, atomic_read(&phys_enc->vblank_refcount)); + enable, phys_enc->vblank_refcount); if (enable) { dpu_core_irq_register_callback(phys_enc->dpu_kms, @@ -333,24 +336,21 @@ static void dpu_encoder_phys_cmd_tearcheck_config( unsigned long vsync_hz; struct dpu_kms *dpu_kms; - if (phys_enc->has_intf_te) { - if (!phys_enc->hw_intf || - !phys_enc->hw_intf->ops.enable_tearcheck) { - DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n"); - return; - } - - DPU_DEBUG_CMDENC(cmd_enc, ""); - } else { - if (!phys_enc->hw_pp || - !phys_enc->hw_pp->ops.enable_tearcheck) { - DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n"); - return; - } - - DPU_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0); + /* + * TODO: if/when resource allocation is refactored, move this to a + * place where the driver can actually return an error. + */ + if (!phys_enc->has_intf_te && + (!phys_enc->hw_pp || + !phys_enc->hw_pp->ops.enable_tearcheck)) { + DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n"); + return; } + DPU_DEBUG_CMDENC(cmd_enc, "intf %d pp %d\n", + phys_enc->hw_intf ? phys_enc->hw_intf->idx - INTF_0 : -1, + phys_enc->hw_pp ? phys_enc->hw_pp->idx - PINGPONG_0 : -1); + mode = &phys_enc->cached_mode; dpu_kms = phys_enc->dpu_kms; @@ -772,12 +772,26 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init( dpu_encoder_phys_init(phys_enc, p); + mutex_init(&phys_enc->vblank_ctl_lock); + phys_enc->vblank_refcount = 0; + dpu_encoder_phys_cmd_init_ops(&phys_enc->ops); phys_enc->intf_mode = INTF_MODE_CMD; cmd_enc->stream_sel = 0; - phys_enc->has_intf_te = test_bit(DPU_INTF_TE, - &phys_enc->hw_intf->cap->features); + if (!phys_enc->hw_intf) { + DPU_ERROR_CMDENC(cmd_enc, "no INTF provided\n"); + return ERR_PTR(-EINVAL); + } + + /* DPU before 5.0 use PINGPONG for TE handling */ + if (phys_enc->dpu_kms->catalog->mdss_ver->core_major_ver >= 5) + phys_enc->has_intf_te = true; + + if (phys_enc->has_intf_te && !phys_enc->hw_intf->ops.enable_tearcheck) { + DPU_ERROR_CMDENC(cmd_enc, "tearcheck not supported\n"); + return ERR_PTR(-EINVAL); + } atomic_set(&cmd_enc->pending_vblank_cnt, 0); init_waitqueue_head(&cmd_enc->pending_vblank_wq); 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 c2189e58de..eeb0acf966 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 @@ -297,7 +297,7 @@ static void dpu_encoder_phys_vid_setup_timing_engine( programmable_fetch_config(phys_enc, &timing_params); } -static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) +static void dpu_encoder_phys_vid_vblank_irq(void *arg) { struct dpu_encoder_phys *phys_enc = arg; struct dpu_hw_ctl *hw_ctl; @@ -334,7 +334,7 @@ static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) DPU_ATRACE_END("vblank_irq"); } -static void dpu_encoder_phys_vid_underrun_irq(void *arg, int irq_idx) +static void dpu_encoder_phys_vid_underrun_irq(void *arg) { struct dpu_encoder_phys *phys_enc = arg; @@ -364,7 +364,8 @@ static int dpu_encoder_phys_vid_control_vblank_irq( int ret = 0; int refcount; - refcount = atomic_read(&phys_enc->vblank_refcount); + mutex_lock(&phys_enc->vblank_ctl_lock); + refcount = phys_enc->vblank_refcount; /* Slave encoders don't report vblank */ if (!dpu_encoder_phys_vid_is_master(phys_enc)) @@ -377,18 +378,26 @@ static int dpu_encoder_phys_vid_control_vblank_irq( } DRM_DEBUG_VBL("id:%u enable=%d/%d\n", DRMID(phys_enc->parent), enable, - atomic_read(&phys_enc->vblank_refcount)); + refcount); - if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1) - ret = dpu_core_irq_register_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_VSYNC], - dpu_encoder_phys_vid_vblank_irq, - phys_enc); - else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0) - ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_VSYNC]); + if (enable) { + if (phys_enc->vblank_refcount == 0) + ret = dpu_core_irq_register_callback(phys_enc->dpu_kms, + phys_enc->irq[INTR_IDX_VSYNC], + dpu_encoder_phys_vid_vblank_irq, + phys_enc); + if (!ret) + phys_enc->vblank_refcount++; + } else if (!enable) { + if (phys_enc->vblank_refcount == 1) + ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, + phys_enc->irq[INTR_IDX_VSYNC]); + if (!ret) + phys_enc->vblank_refcount--; + } end: + mutex_unlock(&phys_enc->vblank_ctl_lock); if (ret) { DRM_ERROR("failed: id:%u intf:%d ret:%d enable:%d refcnt:%d\n", DRMID(phys_enc->parent), @@ -618,7 +627,7 @@ static void dpu_encoder_phys_vid_irq_control(struct dpu_encoder_phys *phys_enc, trace_dpu_enc_phys_vid_irq_ctrl(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0, enable, - atomic_read(&phys_enc->vblank_refcount)); + phys_enc->vblank_refcount); if (enable) { ret = dpu_encoder_phys_vid_control_vblank_irq(phys_enc, true); @@ -713,6 +722,8 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init( DPU_DEBUG_VIDENC(phys_enc, "\n"); dpu_encoder_phys_init(phys_enc, p); + mutex_init(&phys_enc->vblank_ctl_lock); + phys_enc->vblank_refcount = 0; dpu_encoder_phys_vid_init_ops(&phys_enc->ops); phys_enc->intf_mode = INTF_MODE_VIDEO; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c index 78037a6976..0b6a761d68 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c @@ -34,6 +34,23 @@ static bool dpu_encoder_phys_wb_is_master(struct dpu_encoder_phys *phys_enc) return true; } +static bool _dpu_encoder_phys_wb_clk_force_ctrl(struct dpu_hw_wb *wb, + struct dpu_hw_mdp *mdp, + bool enable, bool *forced_on) +{ + if (wb->ops.setup_clk_force_ctrl) { + *forced_on = wb->ops.setup_clk_force_ctrl(wb, enable); + return true; + } + + if (mdp->ops.setup_clk_force_ctrl) { + *forced_on = mdp->ops.setup_clk_force_ctrl(mdp, wb->caps->clk_ctrl, enable); + return true; + } + + return false; +} + /** * dpu_encoder_phys_wb_set_ot_limit - set OT limit for writeback interface * @phys_enc: Pointer to physical encoder @@ -43,6 +60,7 @@ static void dpu_encoder_phys_wb_set_ot_limit( { struct dpu_hw_wb *hw_wb = phys_enc->hw_wb; struct dpu_vbif_set_ot_params ot_params; + bool forced_on = false; memset(&ot_params, 0, sizeof(ot_params)); ot_params.xin_id = hw_wb->caps->xin_id; @@ -52,10 +70,17 @@ static void dpu_encoder_phys_wb_set_ot_limit( ot_params.is_wfd = true; ot_params.frame_rate = drm_mode_vrefresh(&phys_enc->cached_mode); ot_params.vbif_idx = hw_wb->caps->vbif_idx; - ot_params.clk_ctrl = hw_wb->caps->clk_ctrl; ot_params.rd = false; + if (!_dpu_encoder_phys_wb_clk_force_ctrl(hw_wb, phys_enc->dpu_kms->hw_mdp, + true, &forced_on)) + return; + dpu_vbif_set_ot_limit(phys_enc->dpu_kms, &ot_params); + + if (forced_on) + _dpu_encoder_phys_wb_clk_force_ctrl(hw_wb, phys_enc->dpu_kms->hw_mdp, + false, &forced_on); } /** @@ -67,6 +92,7 @@ static void dpu_encoder_phys_wb_set_qos_remap( { struct dpu_hw_wb *hw_wb; struct dpu_vbif_set_qos_params qos_params; + bool forced_on = false; if (!phys_enc || !phys_enc->parent || !phys_enc->parent->crtc) { DPU_ERROR("invalid arguments\n"); @@ -83,7 +109,6 @@ static void dpu_encoder_phys_wb_set_qos_remap( memset(&qos_params, 0, sizeof(qos_params)); qos_params.vbif_idx = hw_wb->caps->vbif_idx; qos_params.xin_id = hw_wb->caps->xin_id; - qos_params.clk_ctrl = hw_wb->caps->clk_ctrl; qos_params.num = hw_wb->idx - WB_0; qos_params.is_rt = false; @@ -92,7 +117,15 @@ static void dpu_encoder_phys_wb_set_qos_remap( qos_params.vbif_idx, qos_params.xin_id, qos_params.is_rt); + if (!_dpu_encoder_phys_wb_clk_force_ctrl(hw_wb, phys_enc->dpu_kms->hw_mdp, + true, &forced_on)) + return; + dpu_vbif_set_qos_remap(phys_enc->dpu_kms, &qos_params); + + if (forced_on) + _dpu_encoder_phys_wb_clk_force_ctrl(hw_wb, phys_enc->dpu_kms->hw_mdp, + false, &forced_on); } /** @@ -345,7 +378,11 @@ static void dpu_encoder_phys_wb_setup( } -static void _dpu_encoder_phys_wb_frame_done_helper(void *arg) +/** + * dpu_encoder_phys_wb_done_irq - writeback interrupt handler + * @arg: Pointer to writeback encoder + */ +static void dpu_encoder_phys_wb_done_irq(void *arg) { struct dpu_encoder_phys *phys_enc = arg; struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); @@ -372,16 +409,6 @@ static void _dpu_encoder_phys_wb_frame_done_helper(void *arg) } /** - * dpu_encoder_phys_wb_done_irq - writeback interrupt handler - * @arg: Pointer to writeback encoder - * @irq_idx: interrupt index - */ -static void dpu_encoder_phys_wb_done_irq(void *arg, int irq_idx) -{ - _dpu_encoder_phys_wb_frame_done_helper(arg); -} - -/** * dpu_encoder_phys_wb_irq_ctrl - irq control of WB * @phys: Pointer to physical encoder * @enable: indicates enable or disable interrupts 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 713dfc0797..7056c08b99 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -79,7 +79,7 @@ (BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA)) #define PINGPONG_SDM845_MASK \ - (BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_TE) | BIT(DPU_PINGPONG_DSC)) + (BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_DSC)) #define PINGPONG_SDM845_TE2_MASK \ (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2)) @@ -100,7 +100,6 @@ #define INTF_SC7180_MASK \ (BIT(DPU_INTF_INPUT_CTRL) | \ - BIT(DPU_INTF_TE) | \ BIT(DPU_INTF_STATUS_SUPPORTED) | \ BIT(DPU_DATA_HCTL_EN)) @@ -250,14 +249,17 @@ static const uint32_t wb2_formats[] = { * SSPP sub blocks config *************************************************************/ +#define SSPP_SCALER_VER(maj, min) (((maj) << 16) | (min)) + /* SSPP common configuration */ -#define _VIG_SBLK(sdma_pri, qseed_ver) \ +#define _VIG_SBLK(sdma_pri, qseed_ver, scaler_ver) \ { \ .maxdwnscale = MAX_DOWNSCALE_RATIO, \ .maxupscale = MAX_UPSCALE_RATIO, \ .smart_dma_priority = sdma_pri, \ .scaler_blk = {.name = "scaler", \ .id = qseed_ver, \ + .version = scaler_ver, \ .base = 0xa00, .len = 0xa0,}, \ .csc_blk = {.name = "csc", \ .id = DPU_SSPP_CSC_10BIT, \ @@ -269,13 +271,14 @@ static const uint32_t wb2_formats[] = { .rotation_cfg = NULL, \ } -#define _VIG_SBLK_ROT(sdma_pri, qseed_ver, rot_cfg) \ +#define _VIG_SBLK_ROT(sdma_pri, qseed_ver, scaler_ver, rot_cfg) \ { \ .maxdwnscale = MAX_DOWNSCALE_RATIO, \ .maxupscale = MAX_UPSCALE_RATIO, \ .smart_dma_priority = sdma_pri, \ .scaler_blk = {.name = "scaler", \ .id = qseed_ver, \ + .version = scaler_ver, \ .base = 0xa00, .len = 0xa0,}, \ .csc_blk = {.name = "csc", \ .id = DPU_SSPP_CSC_10BIT, \ @@ -299,13 +302,17 @@ static const uint32_t wb2_formats[] = { } static const struct dpu_sspp_sub_blks msm8998_vig_sblk_0 = - _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 2)); static const struct dpu_sspp_sub_blks msm8998_vig_sblk_1 = - _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 2)); static const struct dpu_sspp_sub_blks msm8998_vig_sblk_2 = - _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 2)); static const struct dpu_sspp_sub_blks msm8998_vig_sblk_3 = - _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 2)); static const struct dpu_rotation_cfg dpu_rot_sc7280_cfg_v2 = { .rot_maxheight = 1088, @@ -314,13 +321,30 @@ static const struct dpu_rotation_cfg dpu_rot_sc7280_cfg_v2 = { }; static const struct dpu_sspp_sub_blks sdm845_vig_sblk_0 = - _VIG_SBLK(5, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(5, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 3)); static const struct dpu_sspp_sub_blks sdm845_vig_sblk_1 = - _VIG_SBLK(6, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(6, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 3)); static const struct dpu_sspp_sub_blks sdm845_vig_sblk_2 = - _VIG_SBLK(7, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(7, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 3)); static const struct dpu_sspp_sub_blks sdm845_vig_sblk_3 = - _VIG_SBLK(8, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(8, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 3)); + +static const struct dpu_sspp_sub_blks sm8150_vig_sblk_0 = + _VIG_SBLK(5, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 4)); +static const struct dpu_sspp_sub_blks sm8150_vig_sblk_1 = + _VIG_SBLK(6, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 4)); +static const struct dpu_sspp_sub_blks sm8150_vig_sblk_2 = + _VIG_SBLK(7, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 4)); +static const struct dpu_sspp_sub_blks sm8150_vig_sblk_3 = + _VIG_SBLK(8, DPU_SSPP_SCALER_QSEED3, + SSPP_SCALER_VER(1, 4)); static const struct dpu_sspp_sub_blks sdm845_dma_sblk_0 = _DMA_SBLK(1); static const struct dpu_sspp_sub_blks sdm845_dma_sblk_1 = _DMA_SBLK(2); @@ -328,34 +352,60 @@ static const struct dpu_sspp_sub_blks sdm845_dma_sblk_2 = _DMA_SBLK(3); static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK(4); static const struct dpu_sspp_sub_blks sc7180_vig_sblk_0 = - _VIG_SBLK(4, DPU_SSPP_SCALER_QSEED4); + _VIG_SBLK(4, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 0)); static const struct dpu_sspp_sub_blks sc7280_vig_sblk_0 = - _VIG_SBLK_ROT(4, DPU_SSPP_SCALER_QSEED4, &dpu_rot_sc7280_cfg_v2); + _VIG_SBLK_ROT(4, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 0), + &dpu_rot_sc7280_cfg_v2); static const struct dpu_sspp_sub_blks sm6115_vig_sblk_0 = - _VIG_SBLK(2, DPU_SSPP_SCALER_QSEED4); + _VIG_SBLK(2, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 0)); static const struct dpu_sspp_sub_blks sm6125_vig_sblk_0 = - _VIG_SBLK(3, DPU_SSPP_SCALER_QSEED3LITE); + _VIG_SBLK(3, DPU_SSPP_SCALER_QSEED3LITE, + SSPP_SCALER_VER(2, 4)); static const struct dpu_sspp_sub_blks sm8250_vig_sblk_0 = - _VIG_SBLK(5, DPU_SSPP_SCALER_QSEED4); + _VIG_SBLK(5, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 0)); static const struct dpu_sspp_sub_blks sm8250_vig_sblk_1 = - _VIG_SBLK(6, DPU_SSPP_SCALER_QSEED4); + _VIG_SBLK(6, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 0)); static const struct dpu_sspp_sub_blks sm8250_vig_sblk_2 = - _VIG_SBLK(7, DPU_SSPP_SCALER_QSEED4); + _VIG_SBLK(7, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 0)); static const struct dpu_sspp_sub_blks sm8250_vig_sblk_3 = - _VIG_SBLK(8, DPU_SSPP_SCALER_QSEED4); + _VIG_SBLK(8, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 0)); + +static const struct dpu_sspp_sub_blks sm8450_vig_sblk_0 = + _VIG_SBLK(5, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 1)); +static const struct dpu_sspp_sub_blks sm8450_vig_sblk_1 = + _VIG_SBLK(6, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 1)); +static const struct dpu_sspp_sub_blks sm8450_vig_sblk_2 = + _VIG_SBLK(7, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 1)); +static const struct dpu_sspp_sub_blks sm8450_vig_sblk_3 = + _VIG_SBLK(8, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 1)); static const struct dpu_sspp_sub_blks sm8550_vig_sblk_0 = - _VIG_SBLK(7, DPU_SSPP_SCALER_QSEED4); + _VIG_SBLK(7, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 2)); static const struct dpu_sspp_sub_blks sm8550_vig_sblk_1 = - _VIG_SBLK(8, DPU_SSPP_SCALER_QSEED4); + _VIG_SBLK(8, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 2)); static const struct dpu_sspp_sub_blks sm8550_vig_sblk_2 = - _VIG_SBLK(9, DPU_SSPP_SCALER_QSEED4); + _VIG_SBLK(9, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 2)); static const struct dpu_sspp_sub_blks sm8550_vig_sblk_3 = - _VIG_SBLK(10, DPU_SSPP_SCALER_QSEED4); + _VIG_SBLK(10, DPU_SSPP_SCALER_QSEED4, + SSPP_SCALER_VER(3, 2)); static const struct dpu_sspp_sub_blks sm8550_dma_sblk_4 = _DMA_SBLK(5); static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = _DMA_SBLK(6); 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 6c9634209e..6244507530 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -119,7 +119,6 @@ enum { /** * PINGPONG sub-blocks - * @DPU_PINGPONG_TE Tear check block * @DPU_PINGPONG_TE2 Additional tear check block for split pipes * @DPU_PINGPONG_SPLIT PP block supports split fifo * @DPU_PINGPONG_SLAVE PP block is a suitable slave for split fifo @@ -128,8 +127,7 @@ enum { * @DPU_PINGPONG_MAX */ enum { - DPU_PINGPONG_TE = 0x1, - DPU_PINGPONG_TE2, + DPU_PINGPONG_TE2 = 0x1, DPU_PINGPONG_SPLIT, DPU_PINGPONG_SLAVE, DPU_PINGPONG_DITHER, @@ -160,7 +158,6 @@ enum { * INTF sub-blocks * @DPU_INTF_INPUT_CTRL Supports the setting of pp block from which * pixel data arrives to this INTF - * @DPU_INTF_TE INTF block has TE configuration support * @DPU_DATA_HCTL_EN Allows data to be transferred at different rate * than video timing * @DPU_INTF_STATUS_SUPPORTED INTF block has INTF_STATUS register @@ -168,7 +165,6 @@ enum { */ enum { DPU_INTF_INPUT_CTRL = 0x1, - DPU_INTF_TE, DPU_DATA_HCTL_EN, DPU_INTF_STATUS_SUPPORTED, DPU_INTF_MAX @@ -269,7 +265,8 @@ enum { /** * struct dpu_scaler_blk: Scaler information * @info: HW register and features supported by this sub-blk - * @version: qseed block revision + * @version: qseed block revision, on QSEED3+ platforms this is the value of + * scaler_blk.base + QSEED3_HW_VERSION registers. */ struct dpu_scaler_blk { DPU_HW_SUBBLK_INFO; @@ -494,7 +491,7 @@ struct dpu_mdp_cfg { */ struct dpu_ctl_cfg { DPU_HW_BLK_INFO; - s32 intr_start; + unsigned int intr_start; }; /** @@ -557,8 +554,8 @@ struct dpu_dspp_cfg { struct dpu_pingpong_cfg { DPU_HW_BLK_INFO; u32 merge_3d; - s32 intr_done; - s32 intr_rdptr; + unsigned int intr_done; + unsigned int intr_rdptr; const struct dpu_pingpong_sub_blks *sblk; }; @@ -605,9 +602,9 @@ struct dpu_intf_cfg { u32 type; /* interface type*/ u32 controller_id; u32 prog_fetch_lines_worst_case; - s32 intr_underrun; - s32 intr_vsync; - s32 intr_tear_rd_ptr; + unsigned int intr_underrun; + unsigned int intr_vsync; + unsigned int intr_tear_rd_ptr; }; /** @@ -626,7 +623,7 @@ struct dpu_wb_cfg { u8 vbif_idx; u32 maxlinewidth; u32 xin_id; - s32 intr_wb_done; + unsigned int intr_wb_done; const u32 *format_list; u32 num_formats; enum dpu_clk_ctrl_type clk_ctrl; 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 e3c50439f8..088807db2c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -197,27 +197,40 @@ static const struct dpu_intr_reg dpu_intr_set_7xxx[] = { }, }; -#define DPU_IRQ_REG(irq_idx) (irq_idx / 32) -#define DPU_IRQ_MASK(irq_idx) (BIT(irq_idx % 32)) +#define DPU_IRQ_MASK(irq_idx) (BIT(DPU_IRQ_BIT(irq_idx))) + +static inline bool dpu_core_irq_is_valid(unsigned int irq_idx) +{ + return irq_idx && irq_idx <= DPU_NUM_IRQS; +} + +static inline struct dpu_hw_intr_entry *dpu_core_irq_get_entry(struct dpu_hw_intr *intr, + unsigned int irq_idx) +{ + return &intr->irq_tbl[irq_idx - 1]; +} /** * dpu_core_irq_callback_handler - dispatch core interrupts * @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) +static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, unsigned int irq_idx) { - VERB("irq_idx=%d\n", irq_idx); + struct dpu_hw_intr_entry *irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, irq_idx); + + VERB("IRQ=[%d, %d]\n", DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); - if (!dpu_kms->hw_intr->irq_tbl[irq_idx].cb) - DRM_ERROR("no registered cb, idx:%d\n", irq_idx); + if (!irq_entry->cb) + DRM_ERROR("no registered cb, IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); - atomic_inc(&dpu_kms->hw_intr->irq_tbl[irq_idx].count); + atomic_inc(&irq_entry->count); /* * Perform registered function callback */ - dpu_kms->hw_intr->irq_tbl[irq_idx].cb(dpu_kms->hw_intr->irq_tbl[irq_idx].arg, irq_idx); + irq_entry->cb(irq_entry->arg); } irqreturn_t dpu_core_irq(struct msm_kms *kms) @@ -225,7 +238,7 @@ irqreturn_t dpu_core_irq(struct msm_kms *kms) struct dpu_kms *dpu_kms = to_dpu_kms(kms); struct dpu_hw_intr *intr = dpu_kms->hw_intr; int reg_idx; - int irq_idx; + unsigned int irq_idx; u32 irq_status; u32 enable_mask; int bit; @@ -281,7 +294,8 @@ irqreturn_t dpu_core_irq(struct msm_kms *kms) return IRQ_HANDLED; } -static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) +static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr, + unsigned int irq_idx) { int reg_idx; const struct dpu_intr_reg *reg; @@ -291,8 +305,9 @@ static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) if (!intr) return -EINVAL; - if (irq_idx < 0 || irq_idx >= intr->total_irqs) { - pr_err("invalid IRQ index: [%d]\n", irq_idx); + if (!dpu_core_irq_is_valid(irq_idx)) { + pr_err("invalid IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return -EINVAL; } @@ -328,13 +343,15 @@ static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) intr->cache_irq_mask[reg_idx] = cache_irq_mask; } - pr_debug("DPU IRQ %d %senabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", irq_idx, dbgstr, + pr_debug("DPU IRQ=[%d, %d] %senabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), dbgstr, DPU_IRQ_MASK(irq_idx), cache_irq_mask); return 0; } -static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) +static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr, + unsigned int irq_idx) { int reg_idx; const struct dpu_intr_reg *reg; @@ -344,8 +361,9 @@ static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) if (!intr) return -EINVAL; - if (irq_idx < 0 || irq_idx >= intr->total_irqs) { - pr_err("invalid IRQ index: [%d]\n", irq_idx); + if (!dpu_core_irq_is_valid(irq_idx)) { + pr_err("invalid IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return -EINVAL; } @@ -377,7 +395,8 @@ static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) intr->cache_irq_mask[reg_idx] = cache_irq_mask; } - pr_debug("DPU IRQ %d %sdisabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", irq_idx, dbgstr, + pr_debug("DPU IRQ=[%d, %d] %sdisabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), dbgstr, DPU_IRQ_MASK(irq_idx), cache_irq_mask); return 0; @@ -419,7 +438,8 @@ static void dpu_disable_all_irqs(struct dpu_kms *dpu_kms) wmb(); } -u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx) +u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, + unsigned int irq_idx) { struct dpu_hw_intr *intr = dpu_kms->hw_intr; int reg_idx; @@ -429,14 +449,8 @@ u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx) if (!intr) return 0; - if (irq_idx < 0) { - DPU_ERROR("[%pS] invalid irq_idx=%d\n", - __builtin_return_address(0), irq_idx); - return 0; - } - - if (irq_idx < 0 || irq_idx >= intr->total_irqs) { - pr_err("invalid IRQ index: [%d]\n", irq_idx); + if (!dpu_core_irq_is_valid(irq_idx)) { + pr_err("invalid IRQ=[%d, %d]\n", DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return 0; } @@ -462,13 +476,12 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, const struct dpu_mdss_cfg *m) { struct dpu_hw_intr *intr; - int nirq = MDP_INTR_MAX * 32; unsigned int i; if (!addr || !m) return ERR_PTR(-EINVAL); - intr = kzalloc(struct_size(intr, irq_tbl, nirq), GFP_KERNEL); + intr = kzalloc(sizeof(*intr), GFP_KERNEL); if (!intr) return ERR_PTR(-ENOMEM); @@ -479,8 +492,6 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, intr->hw.blk_addr = addr + m->mdp[0].base; - intr->total_irqs = nirq; - intr->irq_mask = BIT(MDP_SSPP_TOP0_INTR) | BIT(MDP_SSPP_TOP0_INTR2) | BIT(MDP_SSPP_TOP0_HIST_INTR); @@ -492,7 +503,7 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, intr->irq_mask |= BIT(MDP_INTFn_INTR(intf->id)); - if (intf->intr_tear_rd_ptr != -1) + if (intf->intr_tear_rd_ptr) intr->irq_mask |= BIT(DPU_IRQ_REG(intf->intr_tear_rd_ptr)); } @@ -506,76 +517,87 @@ void dpu_hw_intr_destroy(struct dpu_hw_intr *intr) kfree(intr); } -int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx, - void (*irq_cb)(void *arg, int irq_idx), - void *irq_arg) +int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, + unsigned int irq_idx, + void (*irq_cb)(void *arg), + void *irq_arg) { + struct dpu_hw_intr_entry *irq_entry; unsigned long irq_flags; int ret; if (!irq_cb) { - DPU_ERROR("invalid ird_idx:%d irq_cb:%ps\n", irq_idx, irq_cb); + DPU_ERROR("invalid IRQ=[%d, %d] irq_cb:%ps\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb); return -EINVAL; } - if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) { - DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx); + if (!dpu_core_irq_is_valid(irq_idx)) { + DPU_ERROR("invalid IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return -EINVAL; } - VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx); + VERB("[%pS] IRQ=[%d, %d]\n", __builtin_return_address(0), + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags); - if (unlikely(WARN_ON(dpu_kms->hw_intr->irq_tbl[irq_idx].cb))) { + irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, irq_idx); + if (unlikely(WARN_ON(irq_entry->cb))) { spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags); return -EBUSY; } - trace_dpu_core_irq_register_callback(irq_idx, irq_cb); - dpu_kms->hw_intr->irq_tbl[irq_idx].arg = irq_arg; - dpu_kms->hw_intr->irq_tbl[irq_idx].cb = irq_cb; + trace_dpu_core_irq_register_callback(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb); + irq_entry->arg = irq_arg; + irq_entry->cb = irq_cb; ret = dpu_hw_intr_enable_irq_locked( dpu_kms->hw_intr, irq_idx); if (ret) - DPU_ERROR("Fail to enable IRQ for irq_idx:%d\n", - irq_idx); + DPU_ERROR("Failed/ to enable IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags); - trace_dpu_irq_register_success(irq_idx); + trace_dpu_irq_register_success(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return 0; } -int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx) +int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, + unsigned int irq_idx) { + struct dpu_hw_intr_entry *irq_entry; unsigned long irq_flags; int ret; - if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) { - DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx); + if (!dpu_core_irq_is_valid(irq_idx)) { + DPU_ERROR("invalid IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return -EINVAL; } - VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx); + VERB("[%pS] IRQ=[%d, %d]\n", __builtin_return_address(0), + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags); - trace_dpu_core_irq_unregister_callback(irq_idx); + trace_dpu_core_irq_unregister_callback(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); ret = dpu_hw_intr_disable_irq_locked(dpu_kms->hw_intr, irq_idx); if (ret) - DPU_ERROR("Fail to disable IRQ for irq_idx:%d: %d\n", - irq_idx, ret); + DPU_ERROR("Failed to disable IRQ=[%d, %d]: %d\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), ret); - dpu_kms->hw_intr->irq_tbl[irq_idx].cb = NULL; - dpu_kms->hw_intr->irq_tbl[irq_idx].arg = NULL; + irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, irq_idx); + irq_entry->cb = NULL; + irq_entry->arg = NULL; spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags); - trace_dpu_irq_unregister_success(irq_idx); + trace_dpu_irq_unregister_success(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return 0; } @@ -584,18 +606,21 @@ int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx) static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v) { struct dpu_kms *dpu_kms = s->private; + struct dpu_hw_intr_entry *irq_entry; unsigned long irq_flags; int i, irq_count; void *cb; - for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) { + for (i = 1; i <= DPU_NUM_IRQS; i++) { spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags); - irq_count = atomic_read(&dpu_kms->hw_intr->irq_tbl[i].count); - cb = dpu_kms->hw_intr->irq_tbl[i].cb; + irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, i); + irq_count = atomic_read(&irq_entry->count); + cb = irq_entry->cb; spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags); if (irq_count || cb) - seq_printf(s, "idx:%d irq:%d cb:%ps\n", i, irq_count, cb); + seq_printf(s, "IRQ=[%d, %d] count:%d cb:%ps\n", + DPU_IRQ_REG(i), DPU_IRQ_BIT(i), irq_count, cb); } return 0; @@ -614,6 +639,7 @@ void dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms, void dpu_core_irq_preinstall(struct msm_kms *kms) { struct dpu_kms *dpu_kms = to_dpu_kms(kms); + struct dpu_hw_intr_entry *irq_entry; int i; pm_runtime_get_sync(&dpu_kms->pdev->dev); @@ -621,22 +647,28 @@ void dpu_core_irq_preinstall(struct msm_kms *kms) dpu_disable_all_irqs(dpu_kms); pm_runtime_put_sync(&dpu_kms->pdev->dev); - for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) - atomic_set(&dpu_kms->hw_intr->irq_tbl[i].count, 0); + for (i = 1; i <= DPU_NUM_IRQS; i++) { + irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, i); + atomic_set(&irq_entry->count, 0); + } } void dpu_core_irq_uninstall(struct msm_kms *kms) { struct dpu_kms *dpu_kms = to_dpu_kms(kms); + struct dpu_hw_intr_entry *irq_entry; int i; if (!dpu_kms->hw_intr) return; pm_runtime_get_sync(&dpu_kms->pdev->dev); - for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) - if (dpu_kms->hw_intr->irq_tbl[i].cb) - DPU_ERROR("irq_idx=%d still enabled/registered\n", i); + for (i = 1; i <= DPU_NUM_IRQS; i++) { + irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, i); + if (irq_entry->cb) + DPU_ERROR("IRQ=[%d, %d] still enabled/registered\n", + DPU_IRQ_REG(i), DPU_IRQ_BIT(i)); + } dpu_clear_irqs(dpu_kms); dpu_disable_all_irqs(dpu_kms); 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 dab761e548..53a21ebc57 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h @@ -36,7 +36,17 @@ enum dpu_hw_intr_reg { #define MDP_INTFn_INTR(intf) (MDP_INTF0_INTR + (intf - INTF_0)) -#define DPU_IRQ_IDX(reg_idx, offset) (reg_idx * 32 + offset) +#define DPU_IRQ_IDX(reg_idx, offset) (1 + reg_idx * 32 + offset) +#define DPU_IRQ_REG(irq_idx) ((irq_idx - 1) / 32) +#define DPU_IRQ_BIT(irq_idx) ((irq_idx - 1) % 32) + +#define DPU_NUM_IRQS (MDP_INTR_MAX * 32) + +struct dpu_hw_intr_entry { + void (*cb)(void *arg); + void *arg; + atomic_t count; +}; /** * struct dpu_hw_intr: hw interrupts handling data structure @@ -44,7 +54,6 @@ enum dpu_hw_intr_reg { * @ops: function pointer mapping for IRQ handling * @cache_irq_mask: array of IRQ enable masks reg storage created during init * @save_irq_status: array of IRQ status reg storage created during init - * @total_irqs: total number of irq_idx mapped in the hw_interrupts * @irq_lock: spinlock for accessing IRQ resources * @irq_cb_tbl: array of IRQ callbacks */ @@ -52,16 +61,11 @@ struct dpu_hw_intr { struct dpu_hw_blk_reg_map hw; u32 cache_irq_mask[MDP_INTR_MAX]; u32 *save_irq_status; - u32 total_irqs; spinlock_t irq_lock; unsigned long irq_mask; const struct dpu_intr_reg *intr_set; - struct { - void (*cb)(void *arg, int irq_idx); - void *arg; - atomic_t count; - } irq_tbl[]; + struct dpu_hw_intr_entry irq_tbl[DPU_NUM_IRQS]; }; /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index da071b1c02..27b9373cd7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -521,32 +521,10 @@ static void dpu_hw_intf_program_intf_cmd_cfg(struct dpu_hw_intf *ctx, if (cmd_mode_cfg->data_compress) intf_cfg2 |= INTF_CFG2_DCE_DATA_COMPRESS; - DPU_REG_WRITE(&ctx->hw, INTF_CONFIG2, intf_cfg2); -} - -static void _setup_intf_ops(struct dpu_hw_intf_ops *ops, - unsigned long cap, const struct dpu_mdss_version *mdss_rev) -{ - ops->setup_timing_gen = dpu_hw_intf_setup_timing_engine; - ops->setup_prg_fetch = dpu_hw_intf_setup_prg_fetch; - ops->get_status = dpu_hw_intf_get_status; - ops->enable_timing = dpu_hw_intf_enable_timing_engine; - ops->get_line_count = dpu_hw_intf_get_line_count; - if (cap & BIT(DPU_INTF_INPUT_CTRL)) - ops->bind_pingpong_blk = dpu_hw_intf_bind_pingpong_blk; - ops->setup_misr = dpu_hw_intf_setup_misr; - ops->collect_misr = dpu_hw_intf_collect_misr; - - if (cap & BIT(DPU_INTF_TE)) { - ops->enable_tearcheck = dpu_hw_intf_enable_te; - ops->disable_tearcheck = dpu_hw_intf_disable_te; - ops->connect_external_te = dpu_hw_intf_connect_external_te; - ops->vsync_sel = dpu_hw_intf_vsync_sel; - ops->disable_autorefresh = dpu_hw_intf_disable_autorefresh; - } + if (cmd_mode_cfg->wide_bus_en) + intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN; - if (mdss_rev->core_major_ver >= 7) - ops->program_intf_cmd_cfg = dpu_hw_intf_program_intf_cmd_cfg; + DPU_REG_WRITE(&ctx->hw, INTF_CONFIG2, intf_cfg2); } struct dpu_hw_intf *dpu_hw_intf_init(const struct dpu_intf_cfg *cfg, @@ -571,7 +549,35 @@ struct dpu_hw_intf *dpu_hw_intf_init(const struct dpu_intf_cfg *cfg, */ c->idx = cfg->id; c->cap = cfg; - _setup_intf_ops(&c->ops, c->cap->features, mdss_rev); + + c->ops.setup_timing_gen = dpu_hw_intf_setup_timing_engine; + c->ops.setup_prg_fetch = dpu_hw_intf_setup_prg_fetch; + c->ops.get_status = dpu_hw_intf_get_status; + c->ops.enable_timing = dpu_hw_intf_enable_timing_engine; + c->ops.get_line_count = dpu_hw_intf_get_line_count; + c->ops.setup_misr = dpu_hw_intf_setup_misr; + c->ops.collect_misr = dpu_hw_intf_collect_misr; + + if (cfg->features & BIT(DPU_INTF_INPUT_CTRL)) + c->ops.bind_pingpong_blk = dpu_hw_intf_bind_pingpong_blk; + + /* INTF TE is only for DSI interfaces */ + if (mdss_rev->core_major_ver >= 5 && cfg->type == INTF_DSI) { + WARN_ON(!cfg->intr_tear_rd_ptr); + + c->ops.enable_tearcheck = dpu_hw_intf_enable_te; + c->ops.disable_tearcheck = dpu_hw_intf_disable_te; + c->ops.connect_external_te = dpu_hw_intf_connect_external_te; + c->ops.vsync_sel = dpu_hw_intf_vsync_sel; + c->ops.disable_autorefresh = dpu_hw_intf_disable_autorefresh; + } + + /* Technically, INTF_CONFIG2 is present for DPU 5.0+, but + * we can configure it for DPU 7.0+ since the wide bus and DSC flags + * would not be set for DPU < 7.0 anyways + */ + if (mdss_rev->core_major_ver >= 7) + c->ops.program_intf_cmd_cfg = dpu_hw_intf_program_intf_cmd_cfg; return c; } 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 4e86108bee..66a5603dc7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h @@ -50,6 +50,7 @@ struct dpu_hw_intf_status { struct dpu_hw_intf_cmd_mode_cfg { u8 data_compress; /* enable data compress between dpu and dsi */ + u8 wide_bus_en; /* enable databus widen mode */ }; /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c index 437d9e62a8..057cac7f5d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c @@ -281,10 +281,24 @@ static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp) return 0; } -static void _setup_pingpong_ops(struct dpu_hw_pingpong *c, - unsigned long features) +struct dpu_hw_pingpong *dpu_hw_pingpong_init(const struct dpu_pingpong_cfg *cfg, + void __iomem *addr, const struct dpu_mdss_version *mdss_rev) { - if (test_bit(DPU_PINGPONG_TE, &features)) { + struct dpu_hw_pingpong *c; + + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) + return ERR_PTR(-ENOMEM); + + c->hw.blk_addr = addr + cfg->base; + c->hw.log_mask = DPU_DBG_MASK_PINGPONG; + + c->idx = cfg->id; + c->caps = cfg; + + if (mdss_rev->core_major_ver < 5) { + WARN_ON(!cfg->intr_rdptr); + c->ops.enable_tearcheck = dpu_hw_pp_enable_te; c->ops.disable_tearcheck = dpu_hw_pp_disable_te; c->ops.connect_external_te = dpu_hw_pp_connect_external_te; @@ -292,31 +306,14 @@ static void _setup_pingpong_ops(struct dpu_hw_pingpong *c, c->ops.disable_autorefresh = dpu_hw_pp_disable_autorefresh; } - if (test_bit(DPU_PINGPONG_DSC, &features)) { + if (test_bit(DPU_PINGPONG_DSC, &cfg->features)) { c->ops.setup_dsc = dpu_hw_pp_setup_dsc; c->ops.enable_dsc = dpu_hw_pp_dsc_enable; c->ops.disable_dsc = dpu_hw_pp_dsc_disable; } - if (test_bit(DPU_PINGPONG_DITHER, &features)) + if (test_bit(DPU_PINGPONG_DITHER, &cfg->features)) c->ops.setup_dither = dpu_hw_pp_setup_dither; -}; - -struct dpu_hw_pingpong *dpu_hw_pingpong_init(const struct dpu_pingpong_cfg *cfg, - void __iomem *addr) -{ - struct dpu_hw_pingpong *c; - - c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) - return ERR_PTR(-ENOMEM); - - c->hw.blk_addr = addr + cfg->base; - c->hw.log_mask = DPU_DBG_MASK_PINGPONG; - - c->idx = cfg->id; - c->caps = cfg; - _setup_pingpong_ops(c, c->caps->features); return c; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h index d3246a9a58..0d541ca5b0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h @@ -123,10 +123,11 @@ static inline struct dpu_hw_pingpong *to_dpu_hw_pingpong(struct dpu_hw_blk *hw) * pingpong catalog entry. * @cfg: Pingpong catalog entry for which driver object is required * @addr: Mapped register io address of MDP + * @mdss_rev: dpu core's major and minor versions * Return: Error code or allocated dpu_hw_pingpong context */ struct dpu_hw_pingpong *dpu_hw_pingpong_init(const struct dpu_pingpong_cfg *cfg, - void __iomem *addr); + void __iomem *addr, const struct dpu_mdss_version *mdss_rev); /** * dpu_hw_pingpong_destroy - destroys pingpong driver context diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index f2192de937..8e3c65989c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -69,6 +69,7 @@ #define SSPP_EXCL_REC_XY_REC1 0x188 #define SSPP_EXCL_REC_SIZE 0x1B4 #define SSPP_EXCL_REC_XY 0x1B8 +#define SSPP_CLK_CTRL 0x330 /* SSPP_SRC_OP_MODE & OP_MODE_REC1 */ #define MDSS_MDP_OP_DEINTERLACE BIT(22) @@ -581,8 +582,18 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe, dpu_setup_cdp(&ctx->hw, cdp_cntl_offset, fmt, enable); } +static bool dpu_hw_sspp_setup_clk_force_ctrl(struct dpu_hw_sspp *ctx, bool enable) +{ + static const struct dpu_clk_ctrl_reg sspp_clk_ctrl = { + .reg_off = SSPP_CLK_CTRL, + .bit_off = 0 + }; + + return dpu_hw_clk_force_ctrl(&ctx->hw, &sspp_clk_ctrl, enable); +} + static void _setup_layer_ops(struct dpu_hw_sspp *c, - unsigned long features) + unsigned long features, const struct dpu_mdss_version *mdss_rev) { c->ops.setup_format = dpu_hw_sspp_setup_format; c->ops.setup_rects = dpu_hw_sspp_setup_rects; @@ -612,6 +623,9 @@ static void _setup_layer_ops(struct dpu_hw_sspp *c, if (test_bit(DPU_SSPP_CDP, &features)) c->ops.setup_cdp = dpu_hw_sspp_setup_cdp; + + if (mdss_rev->core_major_ver >= 9) + c->ops.setup_clk_force_ctrl = dpu_hw_sspp_setup_clk_force_ctrl; } #ifdef CONFIG_DEBUG_FS @@ -672,7 +686,8 @@ int _dpu_hw_sspp_init_debugfs(struct dpu_hw_sspp *hw_pipe, struct dpu_kms *kms, #endif struct dpu_hw_sspp *dpu_hw_sspp_init(const struct dpu_sspp_cfg *cfg, - void __iomem *addr, const struct msm_mdss_data *mdss_data) + void __iomem *addr, const struct msm_mdss_data *mdss_data, + const struct dpu_mdss_version *mdss_rev) { struct dpu_hw_sspp *hw_pipe; @@ -690,7 +705,7 @@ struct dpu_hw_sspp *dpu_hw_sspp_init(const struct dpu_sspp_cfg *cfg, hw_pipe->ubwc = mdss_data; hw_pipe->idx = cfg->id; hw_pipe->cap = cfg; - _setup_layer_ops(hw_pipe, hw_pipe->cap->features); + _setup_layer_ops(hw_pipe, hw_pipe->cap->features, mdss_rev); return hw_pipe; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h index cbf4f95ff0..f93969fddb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h @@ -272,6 +272,14 @@ struct dpu_hw_sspp_ops { bool danger_safe_en); /** + * setup_clk_force_ctrl - setup clock force control + * @ctx: Pointer to pipe context + * @enable: enable clock force if true + */ + bool (*setup_clk_force_ctrl)(struct dpu_hw_sspp *ctx, + bool enable); + + /** * setup_histogram - setup histograms * @ctx: Pointer to pipe context * @cfg: Pointer to histogram configuration @@ -334,9 +342,11 @@ struct dpu_kms; * @cfg: Pipe catalog entry for which driver object is required * @addr: Mapped register io address of MDP * @mdss_data: UBWC / MDSS configuration data + * @mdss_rev: dpu core's major and minor versions */ struct dpu_hw_sspp *dpu_hw_sspp_init(const struct dpu_sspp_cfg *cfg, - void __iomem *addr, const struct msm_mdss_data *mdss_data); + void __iomem *addr, const struct msm_mdss_data *mdss_data, + const struct dpu_mdss_version *mdss_rev); /** * dpu_hw_sspp_destroy(): Destroys SSPP driver context 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 cff48763ce..24e734768a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c @@ -66,34 +66,13 @@ static void dpu_hw_setup_split_pipe(struct dpu_hw_mdp *mdp, static bool dpu_hw_setup_clk_force_ctrl(struct dpu_hw_mdp *mdp, enum dpu_clk_ctrl_type clk_ctrl, bool enable) { - struct dpu_hw_blk_reg_map *c; - u32 reg_off, bit_off; - u32 reg_val, new_val; - bool clk_forced_on; - if (!mdp) return false; - c = &mdp->hw; - if (clk_ctrl <= DPU_CLK_CTRL_NONE || clk_ctrl >= DPU_CLK_CTRL_MAX) return false; - reg_off = mdp->caps->clk_ctrls[clk_ctrl].reg_off; - bit_off = mdp->caps->clk_ctrls[clk_ctrl].bit_off; - - reg_val = DPU_REG_READ(c, reg_off); - - if (enable) - new_val = reg_val | BIT(bit_off); - else - new_val = reg_val & ~BIT(bit_off); - - DPU_REG_WRITE(c, reg_off, new_val); - - clk_forced_on = !(reg_val & BIT(bit_off)); - - return clk_forced_on; + return dpu_hw_clk_force_ctrl(&mdp->hw, &mdp->caps->clk_ctrls[clk_ctrl], enable); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c index 6eee9f68ab..1d4f0b97c3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c @@ -542,3 +542,24 @@ void dpu_setup_cdp(struct dpu_hw_blk_reg_map *c, u32 offset, DPU_REG_WRITE(c, offset, cdp_cntl); } + +bool dpu_hw_clk_force_ctrl(struct dpu_hw_blk_reg_map *c, + const struct dpu_clk_ctrl_reg *clk_ctrl_reg, + bool enable) +{ + u32 reg_val, new_val; + bool clk_forced_on; + + reg_val = DPU_REG_READ(c, clk_ctrl_reg->reg_off); + + if (enable) + new_val = reg_val | BIT(clk_ctrl_reg->bit_off); + else + new_val = reg_val & ~BIT(clk_ctrl_reg->bit_off); + + DPU_REG_WRITE(c, clk_ctrl_reg->reg_off, new_val); + + clk_forced_on = !(reg_val & BIT(clk_ctrl_reg->bit_off)); + + return clk_forced_on; +} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h index 0aed54d7f6..ec09fc3865 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h @@ -365,4 +365,8 @@ int dpu_hw_collect_misr(struct dpu_hw_blk_reg_map *c, u32 misr_signature_offset, u32 *misr_value); +bool dpu_hw_clk_force_ctrl(struct dpu_hw_blk_reg_map *c, + const struct dpu_clk_ctrl_reg *clk_ctrl_reg, + bool enable); + #endif /* _DPU_HW_UTIL_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c index ebc4164003..d49b3ef768 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c @@ -43,6 +43,7 @@ #define WB_MUX 0x150 #define WB_CROP_CTRL 0x154 #define WB_CROP_OFFSET 0x158 +#define WB_CLK_CTRL 0x178 #define WB_CSC_BASE 0x260 #define WB_DST_ADDR_SW_STATUS 0x2B0 #define WB_CDP_CNTL 0x2B4 @@ -86,6 +87,9 @@ static void dpu_hw_wb_setup_format(struct dpu_hw_wb *ctx, dst_format |= BIT(14); /* DST_ALPHA_X */ } + if (DPU_FORMAT_IS_YUV(fmt)) + dst_format |= BIT(15); + pattern = (fmt->element[3] << 24) | (fmt->element[2] << 16) | (fmt->element[1] << 8) | @@ -175,8 +179,18 @@ static void dpu_hw_wb_bind_pingpong_blk( DPU_REG_WRITE(c, WB_MUX, mux_cfg); } +static bool dpu_hw_wb_setup_clk_force_ctrl(struct dpu_hw_wb *ctx, bool enable) +{ + static const struct dpu_clk_ctrl_reg wb_clk_ctrl = { + .reg_off = WB_CLK_CTRL, + .bit_off = 0 + }; + + return dpu_hw_clk_force_ctrl(&ctx->hw, &wb_clk_ctrl, enable); +} + static void _setup_wb_ops(struct dpu_hw_wb_ops *ops, - unsigned long features) + unsigned long features, const struct dpu_mdss_version *mdss_rev) { ops->setup_outaddress = dpu_hw_wb_setup_outaddress; ops->setup_outformat = dpu_hw_wb_setup_format; @@ -192,10 +206,13 @@ static void _setup_wb_ops(struct dpu_hw_wb_ops *ops, if (test_bit(DPU_WB_INPUT_CTRL, &features)) ops->bind_pingpong_blk = dpu_hw_wb_bind_pingpong_blk; + + if (mdss_rev->core_major_ver >= 9) + ops->setup_clk_force_ctrl = dpu_hw_wb_setup_clk_force_ctrl; } struct dpu_hw_wb *dpu_hw_wb_init(const struct dpu_wb_cfg *cfg, - void __iomem *addr) + void __iomem *addr, const struct dpu_mdss_version *mdss_rev) { struct dpu_hw_wb *c; @@ -212,7 +229,7 @@ struct dpu_hw_wb *dpu_hw_wb_init(const struct dpu_wb_cfg *cfg, /* Assign ops */ c->idx = cfg->id; c->caps = cfg; - _setup_wb_ops(&c->ops, c->caps->features); + _setup_wb_ops(&c->ops, c->caps->features, mdss_rev); return c; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h index 2d7db2efa3..88792f450a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h @@ -29,6 +29,7 @@ struct dpu_hw_wb_cfg { * @setup_outformat: setup output format of writeback block from writeback job * @setup_qos_lut: setup qos LUT for writeback block based on input * @setup_cdp: setup chroma down prefetch block for writeback block + * @setup_clk_force_ctrl: setup clock force control * @bind_pingpong_blk: enable/disable the connection with ping-pong block */ struct dpu_hw_wb_ops { @@ -48,6 +49,9 @@ struct dpu_hw_wb_ops { const struct dpu_format *fmt, bool enable); + bool (*setup_clk_force_ctrl)(struct dpu_hw_wb *ctx, + bool enable); + void (*bind_pingpong_blk)(struct dpu_hw_wb *ctx, const enum dpu_pingpong pp); }; @@ -74,10 +78,11 @@ struct dpu_hw_wb { * dpu_hw_wb_init() - Initializes the writeback hw driver object. * @cfg: wb_path catalog entry for which driver object is required * @addr: mapped register io address of MDP + * @mdss_rev: dpu core's major and minor versions * Return: Error code or allocated dpu_hw_wb context */ struct dpu_hw_wb *dpu_hw_wb_init(const struct dpu_wb_cfg *cfg, - void __iomem *addr); + void __iomem *addr, const struct dpu_mdss_version *mdss_rev); /** * dpu_hw_wb_destroy(): Destroy writeback hw driver object. diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index aa6ba2cf4b..fe7267b3bf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -389,8 +389,7 @@ static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms) { struct icc_path *path0; struct icc_path *path1; - struct drm_device *dev = dpu_kms->dev; - struct device *dpu_dev = dev->dev; + struct device *dpu_dev = &dpu_kms->pdev->dev; path0 = msm_icc_get(dpu_dev, "mdp0-mem"); path1 = msm_icc_get(dpu_dev, "mdp1-mem"); @@ -829,21 +828,9 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) dpu_kms->catalog = NULL; - if (dpu_kms->vbif[VBIF_NRT]) - devm_iounmap(&dpu_kms->pdev->dev, dpu_kms->vbif[VBIF_NRT]); - dpu_kms->vbif[VBIF_NRT] = NULL; - - if (dpu_kms->vbif[VBIF_RT]) - devm_iounmap(&dpu_kms->pdev->dev, dpu_kms->vbif[VBIF_RT]); - dpu_kms->vbif[VBIF_RT] = NULL; - if (dpu_kms->hw_mdp) dpu_hw_mdp_destroy(dpu_kms->hw_mdp); dpu_kms->hw_mdp = NULL; - - if (dpu_kms->mmio) - devm_iounmap(&dpu_kms->pdev->dev, dpu_kms->mmio); - dpu_kms->mmio = NULL; } static void dpu_kms_destroy(struct msm_kms *kms) @@ -1079,30 +1066,6 @@ 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"); - if (IS_ERR(dpu_kms->mmio)) { - rc = PTR_ERR(dpu_kms->mmio); - DPU_ERROR("mdp register memory map failed: %d\n", rc); - dpu_kms->mmio = NULL; - goto error; - } - DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio); - - 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"); - if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) { - dpu_kms->vbif[VBIF_NRT] = NULL; - DPU_DEBUG("VBIF NRT is not defined"); - } - - dpu_kms_parse_data_bus_icc_path(dpu_kms); - rc = pm_runtime_resume_and_get(&dpu_kms->pdev->dev); if (rc < 0) goto error; @@ -1241,33 +1204,11 @@ static int dpu_kms_init(struct drm_device *ddev) struct msm_drm_private *priv = ddev->dev_private; struct device *dev = ddev->dev; struct platform_device *pdev = to_platform_device(dev); - struct dpu_kms *dpu_kms; - int irq; + struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); struct dev_pm_opp *opp; int ret = 0; unsigned long max_freq = ULONG_MAX; - dpu_kms = devm_kzalloc(&pdev->dev, sizeof(*dpu_kms), GFP_KERNEL); - if (!dpu_kms) - return -ENOMEM; - - ret = devm_pm_opp_set_clkname(dev, "core"); - if (ret) - return ret; - /* OPP table is optional */ - ret = devm_pm_opp_of_add_table(dev); - if (ret && ret != -ENODEV) { - dev_err(dev, "invalid OPP table in device tree\n"); - return 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; - opp = dev_pm_opp_find_freq_floor(dev, &max_freq); if (!IS_ERR(opp)) dev_pm_opp_put(opp); @@ -1280,33 +1221,79 @@ static int dpu_kms_init(struct drm_device *ddev) return ret; } dpu_kms->dev = ddev; - dpu_kms->pdev = pdev; pm_runtime_enable(&pdev->dev); dpu_kms->rpm_enabled = true; - priv->kms = &dpu_kms->base; - - irq = irq_of_parse_and_map(dpu_kms->pdev->dev.of_node, 0); - if (!irq) { - DPU_ERROR("failed to get irq\n"); - return -EINVAL; - } - dpu_kms->base.irq = irq; - return 0; } static int dpu_dev_probe(struct platform_device *pdev) { - return msm_drv_probe(&pdev->dev, dpu_kms_init); + struct device *dev = &pdev->dev; + struct dpu_kms *dpu_kms; + int irq; + int ret = 0; + + dpu_kms = devm_kzalloc(dev, sizeof(*dpu_kms), GFP_KERNEL); + if (!dpu_kms) + return -ENOMEM; + + dpu_kms->pdev = pdev; + + ret = devm_pm_opp_set_clkname(dev, "core"); + if (ret) + return ret; + /* OPP table is optional */ + ret = devm_pm_opp_of_add_table(dev); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "invalid OPP table in device tree\n"); + + ret = devm_clk_bulk_get_all(&pdev->dev, &dpu_kms->clocks); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to parse clocks\n"); + + dpu_kms->num_clocks = ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return dev_err_probe(dev, irq, "failed to get irq\n"); + + dpu_kms->base.irq = irq; + + dpu_kms->mmio = msm_ioremap(pdev, "mdp"); + if (IS_ERR(dpu_kms->mmio)) { + ret = PTR_ERR(dpu_kms->mmio); + DPU_ERROR("mdp register memory map failed: %d\n", ret); + dpu_kms->mmio = NULL; + return ret; + } + DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio); + + dpu_kms->vbif[VBIF_RT] = msm_ioremap(pdev, "vbif"); + if (IS_ERR(dpu_kms->vbif[VBIF_RT])) { + ret = PTR_ERR(dpu_kms->vbif[VBIF_RT]); + DPU_ERROR("vbif register memory map failed: %d\n", ret); + dpu_kms->vbif[VBIF_RT] = NULL; + return ret; + } + + dpu_kms->vbif[VBIF_NRT] = msm_ioremap_quiet(pdev, "vbif_nrt"); + if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) { + dpu_kms->vbif[VBIF_NRT] = NULL; + DPU_DEBUG("VBIF NRT is not defined"); + } + + ret = dpu_kms_parse_data_bus_icc_path(dpu_kms); + if (ret) + return ret; + + return msm_drv_probe(&pdev->dev, dpu_kms_init, &dpu_kms->base); } -static int dpu_dev_remove(struct platform_device *pdev) +static void dpu_dev_remove(struct platform_device *pdev) { component_master_del(&pdev->dev, &msm_drm_ops); - - return 0; } static int __maybe_unused dpu_runtime_suspend(struct device *dev) @@ -1355,8 +1342,8 @@ static const struct dev_pm_ops dpu_pm_ops = { SET_RUNTIME_PM_OPS(dpu_runtime_suspend, dpu_runtime_resume, NULL) SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) - .prepare = msm_pm_prepare, - .complete = msm_pm_complete, + .prepare = msm_kms_pm_prepare, + .complete = msm_kms_pm_complete, }; static const struct of_device_id dpu_dt_match[] = { @@ -1382,8 +1369,8 @@ MODULE_DEVICE_TABLE(of, dpu_dt_match); static struct platform_driver dpu_driver = { .probe = dpu_dev_probe, - .remove = dpu_dev_remove, - .shutdown = msm_drv_shutdown, + .remove_new = dpu_dev_remove, + .shutdown = msm_kms_shutdown, .driver = { .name = "msm_dpu", .of_match_table = dpu_dt_match, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index b6f53ca6e9..f5473d4dea 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -51,6 +51,7 @@ } while (0) #define DPU_ERROR(fmt, ...) pr_err("[dpu error]" fmt, ##__VA_ARGS__) +#define DPU_ERROR_RATELIMITED(fmt, ...) pr_err_ratelimited("[dpu error]" fmt, ##__VA_ARGS__) /** * ktime_compare_safe - compare two ktime structures diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 0be195f914..3eef5e025e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -333,6 +333,23 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane, enable); } +static bool _dpu_plane_sspp_clk_force_ctrl(struct dpu_hw_sspp *sspp, + struct dpu_hw_mdp *mdp, + bool enable, bool *forced_on) +{ + if (sspp->ops.setup_clk_force_ctrl) { + *forced_on = sspp->ops.setup_clk_force_ctrl(sspp, enable); + return true; + } + + if (mdp->ops.setup_clk_force_ctrl) { + *forced_on = mdp->ops.setup_clk_force_ctrl(mdp, sspp->cap->clk_ctrl, enable); + return true; + } + + return false; +} + /** * _dpu_plane_set_ot_limit - set OT limit for the given plane * @plane: Pointer to drm plane @@ -348,6 +365,7 @@ static void _dpu_plane_set_ot_limit(struct drm_plane *plane, struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_vbif_set_ot_params ot_params; struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); + bool forced_on = false; memset(&ot_params, 0, sizeof(ot_params)); ot_params.xin_id = pipe->sspp->cap->xin_id; @@ -357,10 +375,17 @@ static void _dpu_plane_set_ot_limit(struct drm_plane *plane, ot_params.is_wfd = !pdpu->is_rt_pipe; ot_params.frame_rate = frame_rate; ot_params.vbif_idx = VBIF_RT; - ot_params.clk_ctrl = pipe->sspp->cap->clk_ctrl; ot_params.rd = true; + if (!_dpu_plane_sspp_clk_force_ctrl(pipe->sspp, dpu_kms->hw_mdp, + true, &forced_on)) + return; + dpu_vbif_set_ot_limit(dpu_kms, &ot_params); + + if (forced_on) + _dpu_plane_sspp_clk_force_ctrl(pipe->sspp, dpu_kms->hw_mdp, + false, &forced_on); } /** @@ -374,21 +399,28 @@ static void _dpu_plane_set_qos_remap(struct drm_plane *plane, struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_vbif_set_qos_params qos_params; struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); + bool forced_on = false; memset(&qos_params, 0, sizeof(qos_params)); qos_params.vbif_idx = VBIF_RT; - qos_params.clk_ctrl = pipe->sspp->cap->clk_ctrl; qos_params.xin_id = pipe->sspp->cap->xin_id; qos_params.num = pipe->sspp->idx - SSPP_VIG0; qos_params.is_rt = pdpu->is_rt_pipe; - DPU_DEBUG_PLANE(pdpu, "pipe:%d vbif:%d xin:%d rt:%d, clk_ctrl:%d\n", + DPU_DEBUG_PLANE(pdpu, "pipe:%d vbif:%d xin:%d rt:%d\n", qos_params.num, qos_params.vbif_idx, - qos_params.xin_id, qos_params.is_rt, - qos_params.clk_ctrl); + qos_params.xin_id, qos_params.is_rt); + + if (!_dpu_plane_sspp_clk_force_ctrl(pipe->sspp, dpu_kms->hw_mdp, + true, &forced_on)) + return; dpu_vbif_set_qos_remap(dpu_kms, &qos_params); + + if (forced_on) + _dpu_plane_sspp_clk_force_ctrl(pipe->sspp, dpu_kms->hw_mdp, + false, &forced_on); } static void _dpu_plane_setup_scaler3(struct dpu_hw_sspp *pipe_hw, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index f9215643c7..8759466e2f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -146,7 +146,7 @@ int dpu_rm_init(struct dpu_rm *rm, struct dpu_hw_pingpong *hw; const struct dpu_pingpong_cfg *pp = &cat->pingpong[i]; - hw = dpu_hw_pingpong_init(pp, mmio); + hw = dpu_hw_pingpong_init(pp, mmio, cat->mdss_ver); if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed pingpong object creation: err %d\n", @@ -175,7 +175,7 @@ int dpu_rm_init(struct dpu_rm *rm, struct dpu_hw_wb *hw; const struct dpu_wb_cfg *wb = &cat->wb[i]; - hw = dpu_hw_wb_init(wb, mmio); + hw = dpu_hw_wb_init(wb, mmio, cat->mdss_ver); if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed wb object creation: err %d\n", rc); @@ -231,7 +231,7 @@ int dpu_rm_init(struct dpu_rm *rm, struct dpu_hw_sspp *hw; const struct dpu_sspp_cfg *sspp = &cat->sspp[i]; - hw = dpu_hw_sspp_init(sspp, mmio, mdss_data); + hw = dpu_hw_sspp_init(sspp, mmio, mdss_data, cat->mdss_ver); if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed sspp object creation: err %d\n", rc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h index c74b9be25e..35d03b121a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h @@ -168,46 +168,50 @@ TRACE_EVENT(dpu_perf_crtc_update, ); DECLARE_EVENT_CLASS(dpu_irq_template, - TP_PROTO(int irq_idx), - TP_ARGS(irq_idx), + TP_PROTO(unsigned int irq_reg, unsigned int irq_bit), + TP_ARGS(irq_reg, irq_bit), TP_STRUCT__entry( - __field( int, irq_idx ) + __field( unsigned int, irq_reg ) + __field( unsigned int, irq_bit ) ), TP_fast_assign( - __entry->irq_idx = irq_idx; + __entry->irq_reg = irq_reg; + __entry->irq_bit = irq_bit; ), - TP_printk("irq=%d", __entry->irq_idx) + TP_printk("IRQ=[%d, %d]", __entry->irq_reg, __entry->irq_bit) ); DEFINE_EVENT(dpu_irq_template, dpu_irq_register_success, - TP_PROTO(int irq_idx), - TP_ARGS(irq_idx) + TP_PROTO(unsigned int irq_reg, unsigned int irq_bit), + TP_ARGS(irq_reg, irq_bit) ); DEFINE_EVENT(dpu_irq_template, dpu_irq_unregister_success, - TP_PROTO(int irq_idx), - TP_ARGS(irq_idx) + TP_PROTO(unsigned int irq_reg, unsigned int irq_bit), + TP_ARGS(irq_reg, irq_bit) ); TRACE_EVENT(dpu_enc_irq_wait_success, TP_PROTO(uint32_t drm_id, void *func, - int irq_idx, enum dpu_pingpong pp_idx, int atomic_cnt), - TP_ARGS(drm_id, func, irq_idx, pp_idx, atomic_cnt), + unsigned int irq_reg, unsigned int irq_bit, enum dpu_pingpong pp_idx, int atomic_cnt), + TP_ARGS(drm_id, func, irq_reg, irq_bit, pp_idx, atomic_cnt), TP_STRUCT__entry( __field( uint32_t, drm_id ) __field( void *, func ) - __field( int, irq_idx ) + __field( unsigned int, irq_reg ) + __field( unsigned int, irq_bit ) __field( enum dpu_pingpong, pp_idx ) __field( int, atomic_cnt ) ), TP_fast_assign( __entry->drm_id = drm_id; __entry->func = func; - __entry->irq_idx = irq_idx; + __entry->irq_reg = irq_reg; + __entry->irq_bit = irq_bit; __entry->pp_idx = pp_idx; __entry->atomic_cnt = atomic_cnt; ), - TP_printk("id=%u, callback=%ps, irq=%d, pp=%d, atomic_cnt=%d", + TP_printk("id=%u, callback=%ps, IRQ=[%d, %d], pp=%d, atomic_cnt=%d", __entry->drm_id, __entry->func, - __entry->irq_idx, __entry->pp_idx, __entry->atomic_cnt) + __entry->irq_reg, __entry->irq_bit, __entry->pp_idx, __entry->atomic_cnt) ); DECLARE_EVENT_CLASS(dpu_drm_obj_template, @@ -484,12 +488,13 @@ DEFINE_EVENT(dpu_id_event_template, dpu_crtc_frame_event_more_pending, ); TRACE_EVENT(dpu_enc_wait_event_timeout, - TP_PROTO(uint32_t drm_id, int irq_idx, int rc, s64 time, + TP_PROTO(uint32_t drm_id, unsigned int irq_reg, unsigned int irq_bit, int rc, s64 time, s64 expected_time, int atomic_cnt), - TP_ARGS(drm_id, irq_idx, rc, time, expected_time, atomic_cnt), + TP_ARGS(drm_id, irq_reg, irq_bit, rc, time, expected_time, atomic_cnt), TP_STRUCT__entry( __field( uint32_t, drm_id ) - __field( int, irq_idx ) + __field( unsigned int, irq_reg ) + __field( unsigned int, irq_bit ) __field( int, rc ) __field( s64, time ) __field( s64, expected_time ) @@ -497,14 +502,15 @@ TRACE_EVENT(dpu_enc_wait_event_timeout, ), TP_fast_assign( __entry->drm_id = drm_id; - __entry->irq_idx = irq_idx; + __entry->irq_reg = irq_reg; + __entry->irq_bit = irq_bit; __entry->rc = rc; __entry->time = time; __entry->expected_time = expected_time; __entry->atomic_cnt = atomic_cnt; ), - TP_printk("id=%u, irq_idx=%d, rc=%d, time=%lld, expected=%lld cnt=%d", - __entry->drm_id, __entry->irq_idx, __entry->rc, __entry->time, + TP_printk("id=%u, IRQ=[%d, %d], rc=%d, time=%lld, expected=%lld cnt=%d", + __entry->drm_id, __entry->irq_reg, __entry->irq_bit, __entry->rc, __entry->time, __entry->expected_time, __entry->atomic_cnt) ); @@ -863,30 +869,34 @@ TRACE_EVENT(dpu_intf_connect_ext_te, ); TRACE_EVENT(dpu_core_irq_register_callback, - TP_PROTO(int irq_idx, void *callback), - TP_ARGS(irq_idx, callback), + TP_PROTO(unsigned int irq_reg, unsigned int irq_bit, void *callback), + TP_ARGS(irq_reg, irq_bit, callback), TP_STRUCT__entry( - __field( int, irq_idx ) + __field( unsigned int, irq_reg ) + __field( unsigned int, irq_bit ) __field( void *, callback) ), TP_fast_assign( - __entry->irq_idx = irq_idx; + __entry->irq_reg = irq_reg; + __entry->irq_bit = irq_bit; __entry->callback = callback; ), - TP_printk("irq_idx:%d callback:%ps", __entry->irq_idx, + TP_printk("IRQ=[%d, %d] callback:%ps", __entry->irq_reg, __entry->irq_bit, __entry->callback) ); TRACE_EVENT(dpu_core_irq_unregister_callback, - TP_PROTO(int irq_idx), - TP_ARGS(irq_idx), + TP_PROTO(unsigned int irq_reg, unsigned int irq_bit), + TP_ARGS(irq_reg, irq_bit), TP_STRUCT__entry( - __field( int, irq_idx ) + __field( unsigned int, irq_reg ) + __field( unsigned int, irq_bit ) ), TP_fast_assign( - __entry->irq_idx = irq_idx; + __entry->irq_reg = irq_reg; + __entry->irq_bit = irq_bit; ), - TP_printk("irq_idx:%d", __entry->irq_idx) + TP_printk("IRQ=[%d, %d]", __entry->irq_reg, __entry->irq_bit) ); TRACE_EVENT(dpu_core_perf_update_clk, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c index 1305e250b7..47c02b98ea 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c @@ -169,23 +169,16 @@ void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms, struct dpu_vbif_set_ot_params *params) { struct dpu_hw_vbif *vbif; - struct dpu_hw_mdp *mdp; - bool forced_on = false; u32 ot_lim; int ret; - mdp = dpu_kms->hw_mdp; - vbif = dpu_get_vbif(dpu_kms, params->vbif_idx); - if (!vbif || !mdp) { - DRM_DEBUG_ATOMIC("invalid arguments vbif %d mdp %d\n", - vbif != NULL, mdp != NULL); + if (!vbif) { + DRM_DEBUG_ATOMIC("invalid arguments vbif %d\n", vbif != NULL); return; } - if (!mdp->ops.setup_clk_force_ctrl || - !vbif->ops.set_limit_conf || - !vbif->ops.set_halt_ctrl) + if (!vbif->ops.set_limit_conf || !vbif->ops.set_halt_ctrl) return; /* set write_gather_en for all write clients */ @@ -200,8 +193,6 @@ void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms, trace_dpu_perf_set_ot(params->num, params->xin_id, ot_lim, params->vbif_idx); - forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true); - vbif->ops.set_limit_conf(vbif, params->xin_id, params->rd, ot_lim); vbif->ops.set_halt_ctrl(vbif, params->xin_id, true); @@ -211,25 +202,19 @@ void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms, trace_dpu_vbif_wait_xin_halt_fail(vbif->idx, params->xin_id); vbif->ops.set_halt_ctrl(vbif, params->xin_id, false); - - if (forced_on) - mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false); } void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, struct dpu_vbif_set_qos_params *params) { struct dpu_hw_vbif *vbif; - struct dpu_hw_mdp *mdp; - bool forced_on = false; const struct dpu_vbif_qos_tbl *qos_tbl; int i; - if (!params || !dpu_kms->hw_mdp) { + if (!params) { DPU_ERROR("invalid arguments\n"); return; } - mdp = dpu_kms->hw_mdp; vbif = dpu_get_vbif(dpu_kms, params->vbif_idx); @@ -238,7 +223,7 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, return; } - if (!vbif->ops.set_qos_remap || !mdp->ops.setup_clk_force_ctrl) { + if (!vbif->ops.set_qos_remap) { DRM_DEBUG_ATOMIC("qos remap not supported\n"); return; } @@ -251,8 +236,6 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, return; } - forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true); - for (i = 0; i < qos_tbl->npriority_lvl; i++) { DRM_DEBUG_ATOMIC("%s xin:%d lvl:%d/%d\n", dpu_vbif_name(params->vbif_idx), params->xin_id, i, @@ -260,9 +243,6 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, vbif->ops.set_qos_remap(vbif, params->xin_id, i, qos_tbl->priority_lvl[i]); } - - if (forced_on) - mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false); } void dpu_vbif_clear_errors(struct dpu_kms *dpu_kms) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h index ab490177d8..e1b1f7f4e4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h @@ -16,13 +16,11 @@ struct dpu_vbif_set_ot_params { bool rd; bool is_wfd; u32 vbif_idx; - u32 clk_ctrl; }; struct dpu_vbif_set_memtype_params { u32 xin_id; u32 vbif_idx; - u32 clk_ctrl; bool is_cacheable; }; @@ -30,14 +28,12 @@ struct dpu_vbif_set_memtype_params { * struct dpu_vbif_set_qos_params - QoS remapper parameter * @vbif_idx: vbif identifier * @xin_id: client interface identifier - * @clk_ctrl: clock control identifier of the xin * @num: pipe identifier (debug only) * @is_rt: true if pipe is used in real-time use case */ struct dpu_vbif_set_qos_params { u32 vbif_idx; u32 xin_id; - u32 clk_ctrl; u32 num; bool is_rt; }; diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index 700df4040e..4ba1cb74ad 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -135,8 +135,6 @@ static void mdp4_destroy(struct msm_kms *kms) pm_runtime_disable(dev); mdp_kms_destroy(&mdp4_kms->base); - - kfree(mdp4_kms); } static const struct mdp_kms_funcs kms_funcs = { @@ -380,56 +378,27 @@ static int mdp4_kms_init(struct drm_device *dev) { struct platform_device *pdev = to_platform_device(dev->dev); struct msm_drm_private *priv = dev->dev_private; - struct mdp4_kms *mdp4_kms; + struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(priv->kms)); struct msm_kms *kms = NULL; struct msm_mmu *mmu; struct msm_gem_address_space *aspace; - int irq, ret; + int ret; u32 major, minor; unsigned long max_clk; /* TODO: Chips that aren't apq8064 have a 200 Mhz max_clk */ max_clk = 266667000; - mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL); - if (!mdp4_kms) { - DRM_DEV_ERROR(dev->dev, "failed to allocate kms\n"); - return -ENOMEM; - } - ret = mdp_kms_init(&mdp4_kms->base, &kms_funcs); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to init kms\n"); goto fail; } - priv->kms = &mdp4_kms->base.base; kms = priv->kms; mdp4_kms->dev = dev; - mdp4_kms->mmio = msm_ioremap(pdev, NULL); - if (IS_ERR(mdp4_kms->mmio)) { - ret = PTR_ERR(mdp4_kms->mmio); - goto fail; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - ret = irq; - goto fail; - } - - kms->irq = irq; - - /* NOTE: driver for this regulator still missing upstream.. use - * _get_exclusive() and ignore the error if it does not exist - * (and hope that the bootloader left it on for us) - */ - mdp4_kms->vdd = devm_regulator_get_exclusive(&pdev->dev, "vdd"); - if (IS_ERR(mdp4_kms->vdd)) - mdp4_kms->vdd = NULL; - if (mdp4_kms->vdd) { ret = regulator_enable(mdp4_kms->vdd); if (ret) { @@ -438,24 +407,6 @@ static int mdp4_kms_init(struct drm_device *dev) } } - mdp4_kms->clk = devm_clk_get(&pdev->dev, "core_clk"); - if (IS_ERR(mdp4_kms->clk)) { - DRM_DEV_ERROR(dev->dev, "failed to get core_clk\n"); - ret = PTR_ERR(mdp4_kms->clk); - goto fail; - } - - mdp4_kms->pclk = devm_clk_get(&pdev->dev, "iface_clk"); - if (IS_ERR(mdp4_kms->pclk)) - mdp4_kms->pclk = NULL; - - mdp4_kms->axi_clk = devm_clk_get(&pdev->dev, "bus_clk"); - if (IS_ERR(mdp4_kms->axi_clk)) { - DRM_DEV_ERROR(dev->dev, "failed to get axi_clk\n"); - ret = PTR_ERR(mdp4_kms->axi_clk); - goto fail; - } - clk_set_rate(mdp4_kms->clk, max_clk); read_mdp_hw_revision(mdp4_kms, &major, &minor); @@ -470,10 +421,9 @@ static int mdp4_kms_init(struct drm_device *dev) mdp4_kms->rev = minor; if (mdp4_kms->rev >= 2) { - mdp4_kms->lut_clk = devm_clk_get(&pdev->dev, "lut_clk"); - if (IS_ERR(mdp4_kms->lut_clk)) { + if (!mdp4_kms->lut_clk) { DRM_DEV_ERROR(dev->dev, "failed to get lut_clk\n"); - ret = PTR_ERR(mdp4_kms->lut_clk); + ret = -ENODEV; goto fail; } clk_set_rate(mdp4_kms->lut_clk, max_clk); @@ -551,20 +501,64 @@ fail: } static const struct dev_pm_ops mdp4_pm_ops = { - .prepare = msm_pm_prepare, - .complete = msm_pm_complete, + .prepare = msm_kms_pm_prepare, + .complete = msm_kms_pm_complete, }; static int mdp4_probe(struct platform_device *pdev) { - return msm_drv_probe(&pdev->dev, mdp4_kms_init); + struct device *dev = &pdev->dev; + struct mdp4_kms *mdp4_kms; + int irq; + + mdp4_kms = devm_kzalloc(dev, sizeof(*mdp4_kms), GFP_KERNEL); + if (!mdp4_kms) + return dev_err_probe(dev, -ENOMEM, "failed to allocate kms\n"); + + mdp4_kms->mmio = msm_ioremap(pdev, NULL); + if (IS_ERR(mdp4_kms->mmio)) + return PTR_ERR(mdp4_kms->mmio); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return dev_err_probe(dev, irq, "failed to get irq\n"); + + mdp4_kms->base.base.irq = irq; + + /* NOTE: driver for this regulator still missing upstream.. use + * _get_exclusive() and ignore the error if it does not exist + * (and hope that the bootloader left it on for us) + */ + mdp4_kms->vdd = devm_regulator_get_exclusive(&pdev->dev, "vdd"); + if (IS_ERR(mdp4_kms->vdd)) + mdp4_kms->vdd = NULL; + + mdp4_kms->clk = devm_clk_get(&pdev->dev, "core_clk"); + if (IS_ERR(mdp4_kms->clk)) + return dev_err_probe(dev, PTR_ERR(mdp4_kms->clk), "failed to get core_clk\n"); + + mdp4_kms->pclk = devm_clk_get(&pdev->dev, "iface_clk"); + if (IS_ERR(mdp4_kms->pclk)) + mdp4_kms->pclk = NULL; + + mdp4_kms->axi_clk = devm_clk_get(&pdev->dev, "bus_clk"); + if (IS_ERR(mdp4_kms->axi_clk)) + return dev_err_probe(dev, PTR_ERR(mdp4_kms->axi_clk), "failed to get axi_clk\n"); + + /* + * This is required for revn >= 2. Handle errors here and let the kms + * init bail out if the clock is not provided. + */ + mdp4_kms->lut_clk = devm_clk_get_optional(&pdev->dev, "lut_clk"); + if (IS_ERR(mdp4_kms->lut_clk)) + return dev_err_probe(dev, PTR_ERR(mdp4_kms->lut_clk), "failed to get lut_clk\n"); + + return msm_drv_probe(&pdev->dev, mdp4_kms_init, &mdp4_kms->base.base); } -static int mdp4_remove(struct platform_device *pdev) +static void mdp4_remove(struct platform_device *pdev) { component_master_del(&pdev->dev, &msm_drm_ops); - - return 0; } static const struct of_device_id mdp4_dt_match[] = { @@ -575,8 +569,8 @@ MODULE_DEVICE_TABLE(of, mdp4_dt_match); static struct platform_driver mdp4_platform_driver = { .probe = mdp4_probe, - .remove = mdp4_remove, - .shutdown = msm_drv_shutdown, + .remove_new = mdp4_remove, + .shutdown = msm_kms_shutdown, .driver = { .name = "mdp4", .of_match_table = mdp4_dt_match, diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 92bf9d949d..ec933d597e 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -554,20 +554,16 @@ static int mdp5_kms_init(struct drm_device *dev) struct platform_device *pdev; struct mdp5_kms *mdp5_kms; struct mdp5_cfg *config; - struct msm_kms *kms; + struct msm_kms *kms = priv->kms; struct msm_gem_address_space *aspace; - int irq, i, ret; + int i, ret; ret = mdp5_init(to_platform_device(dev->dev), dev); if (ret) return ret; - /* priv->kms would have been populated by the MDP5 driver */ - kms = priv->kms; - if (!kms) - return -ENOMEM; - mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); + pdev = mdp5_kms->pdev; ret = mdp_kms_init(&mdp5_kms->base, &kms_funcs); @@ -576,15 +572,6 @@ static int mdp5_kms_init(struct drm_device *dev) goto fail; } - irq = irq_of_parse_and_map(pdev->dev.of_node, 0); - if (!irq) { - ret = -EINVAL; - DRM_DEV_ERROR(&pdev->dev, "failed to get irq\n"); - goto fail; - } - - kms->irq = irq; - config = mdp5_cfg_get_config(mdp5_kms->cfg); /* make sure things are off before attaching iommu (bootloader could @@ -787,60 +774,23 @@ static int interface_init(struct mdp5_kms *mdp5_kms) static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; - struct mdp5_kms *mdp5_kms; + struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms)); struct mdp5_cfg *config; u32 major, minor; int ret; - mdp5_kms = devm_kzalloc(&pdev->dev, sizeof(*mdp5_kms), GFP_KERNEL); - if (!mdp5_kms) { - ret = -ENOMEM; - goto fail; - } - - spin_lock_init(&mdp5_kms->resource_lock); - mdp5_kms->dev = dev; - mdp5_kms->pdev = pdev; ret = mdp5_global_obj_init(mdp5_kms); if (ret) goto fail; - mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys"); - if (IS_ERR(mdp5_kms->mmio)) { - ret = PTR_ERR(mdp5_kms->mmio); - goto fail; - } - - /* mandatory clocks: */ - ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus", true); - if (ret) - goto fail; - ret = get_clk(pdev, &mdp5_kms->ahb_clk, "iface", true); - if (ret) - goto fail; - ret = get_clk(pdev, &mdp5_kms->core_clk, "core", true); - if (ret) - goto fail; - ret = get_clk(pdev, &mdp5_kms->vsync_clk, "vsync", true); - if (ret) - goto fail; - - /* optional clocks: */ - get_clk(pdev, &mdp5_kms->lut_clk, "lut", false); - get_clk(pdev, &mdp5_kms->tbu_clk, "tbu", false); - get_clk(pdev, &mdp5_kms->tbu_rt_clk, "tbu_rt", false); - /* we need to set a default rate before enabling. Set a safe * rate first, then figure out hw revision, and then set a * more optimal rate: */ clk_set_rate(mdp5_kms->core_clk, 200000000); - /* set uninit-ed kms */ - priv->kms = &mdp5_kms->base.base; - pm_runtime_enable(&pdev->dev); mdp5_kms->rpm_enabled = true; @@ -894,8 +844,7 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) return 0; fail: - if (mdp5_kms) - mdp5_destroy(mdp5_kms); + mdp5_destroy(mdp5_kms); return ret; } @@ -931,22 +880,59 @@ static int mdp5_setup_interconnect(struct platform_device *pdev) static int mdp5_dev_probe(struct platform_device *pdev) { - int ret; + struct mdp5_kms *mdp5_kms; + int ret, irq; DBG(""); + mdp5_kms = devm_kzalloc(&pdev->dev, sizeof(*mdp5_kms), GFP_KERNEL); + if (!mdp5_kms) + return -ENOMEM; + ret = mdp5_setup_interconnect(pdev); if (ret) return ret; - return msm_drv_probe(&pdev->dev, mdp5_kms_init); + mdp5_kms->pdev = pdev; + + spin_lock_init(&mdp5_kms->resource_lock); + + mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys"); + if (IS_ERR(mdp5_kms->mmio)) + return PTR_ERR(mdp5_kms->mmio); + + /* mandatory clocks: */ + ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus", true); + if (ret) + return ret; + ret = get_clk(pdev, &mdp5_kms->ahb_clk, "iface", true); + if (ret) + return ret; + ret = get_clk(pdev, &mdp5_kms->core_clk, "core", true); + if (ret) + return ret; + ret = get_clk(pdev, &mdp5_kms->vsync_clk, "vsync", true); + if (ret) + return ret; + + /* optional clocks: */ + get_clk(pdev, &mdp5_kms->lut_clk, "lut", false); + get_clk(pdev, &mdp5_kms->tbu_clk, "tbu", false); + get_clk(pdev, &mdp5_kms->tbu_rt_clk, "tbu_rt", false); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return dev_err_probe(&pdev->dev, irq, "failed to get irq\n"); + + mdp5_kms->base.base.irq = irq; + + return msm_drv_probe(&pdev->dev, mdp5_kms_init, &mdp5_kms->base.base); } -static int mdp5_dev_remove(struct platform_device *pdev) +static void mdp5_dev_remove(struct platform_device *pdev) { DBG(""); component_master_del(&pdev->dev, &msm_drm_ops); - return 0; } static __maybe_unused int mdp5_runtime_suspend(struct device *dev) @@ -973,8 +959,8 @@ static __maybe_unused int mdp5_runtime_resume(struct device *dev) static const struct dev_pm_ops mdp5_pm_ops = { SET_RUNTIME_PM_OPS(mdp5_runtime_suspend, mdp5_runtime_resume, NULL) - .prepare = msm_pm_prepare, - .complete = msm_pm_complete, + .prepare = msm_kms_pm_prepare, + .complete = msm_kms_pm_complete, }; static const struct of_device_id mdp5_dt_match[] = { @@ -987,8 +973,8 @@ MODULE_DEVICE_TABLE(of, mdp5_dt_match); static struct platform_driver mdp5_driver = { .probe = mdp5_dev_probe, - .remove = mdp5_dev_remove, - .shutdown = msm_drv_shutdown, + .remove_new = mdp5_dev_remove, + .shutdown = msm_kms_shutdown, .driver = { .name = "msm_mdp", .of_match_table = mdp5_dt_match, diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c index 56a3063545..b68682c1b5 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c @@ -379,7 +379,7 @@ struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct mdp5_smp_ { struct mdp5_smp_state *state; struct mdp5_global_state *global_state; - struct mdp5_smp *smp = NULL; + struct mdp5_smp *smp; int ret; smp = kzalloc(sizeof(*smp), GFP_KERNEL); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 77a8d9366e..fb588fde29 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -135,11 +135,6 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl) tbd = dp_link_get_test_bits_depth(ctrl->link, ctrl->panel->dp_mode.bpp); - if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN) { - pr_debug("BIT_DEPTH not set. Configure default\n"); - tbd = DP_TEST_BIT_DEPTH_8; - } - config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT; /* Num of Lanes */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 76f1395401..4f89c99395 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -88,7 +88,6 @@ struct dp_display_private { bool audio_supported; struct drm_device *drm_dev; - struct platform_device *pdev; struct dentry *root; struct dp_parser *parser; @@ -171,6 +170,11 @@ static const struct msm_dp_desc sm8350_dp_descs[] = { {} }; +static const struct msm_dp_desc sm8650_dp_descs[] = { + { .io_start = 0x0af54000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, + {} +}; + static const struct of_device_id dp_dt_match[] = { { .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_descs }, { .compatible = "qcom,sc7280-dp", .data = &sc7280_dp_descs }, @@ -181,6 +185,7 @@ static const struct of_device_id dp_dt_match[] = { { .compatible = "qcom,sc8280xp-edp", .data = &sc8280xp_edp_descs }, { .compatible = "qcom,sdm845-dp", .data = &sc7180_dp_descs }, { .compatible = "qcom,sm8350-dp", .data = &sm8350_dp_descs }, + { .compatible = "qcom,sm8650-dp", .data = &sm8650_dp_descs }, {} }; @@ -341,21 +346,6 @@ static const struct component_ops dp_display_comp_ops = { .unbind = dp_display_unbind, }; -static bool dp_display_is_ds_bridge(struct dp_panel *panel) -{ - return (panel->dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_PRESENT); -} - -static bool dp_display_is_sink_count_zero(struct dp_display_private *dp) -{ - drm_dbg_dp(dp->drm_dev, "present=%#x sink_count=%d\n", - dp->panel->dpcd[DP_DOWNSTREAMPORT_PRESENT], - dp->link->sink_count); - return dp_display_is_ds_bridge(dp->panel) && - (dp->link->sink_count == 0); -} - static void dp_display_send_hpd_event(struct msm_dp *dp_display) { struct dp_display_private *dp; @@ -379,8 +369,14 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp, } /* reset video pattern flag on disconnect */ - if (!hpd) + if (!hpd) { dp->panel->video_test = false; + if (!dp->dp_display.is_edp) + drm_dp_set_subconnector_property(dp->dp_display.connector, + connector_status_disconnected, + dp->panel->dpcd, + dp->panel->downstream_ports); + } dp->dp_display.is_connected = hpd; @@ -408,6 +404,12 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp_link_process_request(dp->link); + if (!dp->dp_display.is_edp) + drm_dp_set_subconnector_property(dp->dp_display.connector, + connector_status_connected, + dp->panel->dpcd, + dp->panel->downstream_ports); + edid = dp->panel->edid; dp->dp_display.psr_supported = dp->panel->psr_cap.version && psr_enabled; @@ -514,7 +516,7 @@ static int dp_display_handle_port_ststus_changed(struct dp_display_private *dp) { int rc = 0; - if (dp_display_is_sink_count_zero(dp)) { + if (drm_dp_is_branch(dp->panel->dpcd) && dp->link->sink_count == 0) { drm_dbg_dp(dp->drm_dev, "sink count is zero, nothing to do\n"); if (dp->hpd_state != ST_DISCONNECTED) { dp->hpd_state = ST_DISCONNECT_PENDING; @@ -603,7 +605,7 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) return 0; } - ret = dp_display_usbpd_configure_cb(&dp->pdev->dev); + ret = dp_display_usbpd_configure_cb(&dp->dp_display.pdev->dev); if (ret) { /* link train failed */ dp->hpd_state = ST_DISCONNECTED; } else { @@ -651,7 +653,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) if (dp->link->sink_count == 0) { dp_display_host_phy_exit(dp); } - dp_display_notify_disconnect(&dp->pdev->dev); + dp_display_notify_disconnect(&dp->dp_display.pdev->dev); mutex_unlock(&dp->event_mutex); return 0; } else if (state == ST_DISCONNECT_PENDING) { @@ -661,7 +663,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) dp_ctrl_off_link(dp->ctrl); dp_display_host_phy_exit(dp); dp->hpd_state = ST_DISCONNECTED; - dp_display_notify_disconnect(&dp->pdev->dev); + dp_display_notify_disconnect(&dp->dp_display.pdev->dev); mutex_unlock(&dp->event_mutex); return 0; } @@ -670,7 +672,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) * We don't need separate work for disconnect as * connect/attention interrupts are disabled */ - dp_display_notify_disconnect(&dp->pdev->dev); + dp_display_notify_disconnect(&dp->dp_display.pdev->dev); if (state == ST_DISPLAY_OFF) { dp->hpd_state = ST_DISCONNECTED; @@ -712,7 +714,7 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) return 0; } - dp_display_usbpd_attention_cb(&dp->pdev->dev); + dp_display_usbpd_attention_cb(&dp->dp_display.pdev->dev); drm_dbg_dp(dp->drm_dev, "After, type=%d hpd_state=%d\n", dp->dp_display.connector_type, state); @@ -733,12 +735,12 @@ static void dp_display_deinit_sub_modules(struct dp_display_private *dp) static int dp_init_sub_modules(struct dp_display_private *dp) { int rc = 0; - struct device *dev = &dp->pdev->dev; + struct device *dev = &dp->dp_display.pdev->dev; struct dp_panel_in panel_in = { .dev = dev, }; - dp->parser = dp_parser_get(dp->pdev); + dp->parser = dp_parser_get(dp->dp_display.pdev); if (IS_ERR(dp->parser)) { rc = PTR_ERR(dp->parser); DRM_ERROR("failed to initialize parser, rc = %d\n", rc); @@ -799,7 +801,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error_ctrl; } - dp->audio = dp_audio_get(dp->pdev, dp->panel, dp->catalog); + dp->audio = dp_audio_get(dp->dp_display.pdev, dp->panel, dp->catalog); if (IS_ERR(dp->audio)) { rc = PTR_ERR(dp->audio); pr_err("failed to initialize audio, rc = %d\n", rc); @@ -1205,7 +1207,7 @@ int dp_display_request_irq(struct msm_dp *dp_display) dp = container_of(dp_display, struct dp_display_private, dp_display); - dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0); + dp->irq = irq_of_parse_and_map(dp->dp_display.pdev->dev.of_node, 0); if (!dp->irq) { DRM_ERROR("failed to get irq\n"); return -EINVAL; @@ -1261,7 +1263,7 @@ static int dp_display_probe(struct platform_device *pdev) if (!desc) return -EINVAL; - dp->pdev = pdev; + dp->dp_display.pdev = pdev; dp->name = "drm_dp"; dp->id = desc->id; dp->dp_display.connector_type = desc->connector_type; @@ -1296,7 +1298,7 @@ static int dp_display_probe(struct platform_device *pdev) return rc; } -static int dp_display_remove(struct platform_device *pdev) +static void dp_display_remove(struct platform_device *pdev) { struct dp_display_private *dp = dev_get_dp_display_private(&pdev->dev); @@ -1304,8 +1306,6 @@ static int dp_display_remove(struct platform_device *pdev) dp_display_deinit_sub_modules(dp); platform_set_drvdata(pdev, NULL); - - return 0; } static int dp_pm_resume(struct device *dev) @@ -1415,7 +1415,7 @@ static const struct dev_pm_ops dp_pm_ops = { static struct platform_driver dp_display_driver = { .probe = dp_display_probe, - .remove = dp_display_remove, + .remove_new = dp_display_remove, .driver = { .name = "msm-dp-display", .of_match_table = dp_dt_match, @@ -1469,7 +1469,7 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor) int rc; dp = container_of(dp_display, struct dp_display_private, dp_display); - dev = &dp->pdev->dev; + dev = &dp->dp_display.pdev->dev; dp->debug = dp_debug_get(dev, dp->panel, dp->link, dp->dp_display.connector, @@ -1489,7 +1489,7 @@ static int dp_display_get_next_bridge(struct msm_dp *dp) struct device *dev; dp_priv = container_of(dp, struct dp_display_private, dp_display); - dev = &dp_priv->pdev->dev; + dev = &dp_priv->dp_display.pdev->dev; aux_bus = of_get_child_by_name(dev->of_node, "aux-bus"); if (aux_bus && dp->is_edp) { @@ -1541,7 +1541,6 @@ error: int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, struct drm_encoder *encoder) { - struct msm_drm_private *priv = dev->dev_private; struct dp_display_private *dp_priv; int ret; @@ -1559,17 +1558,13 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, if (ret) return ret; - dp_display->bridge = dp_bridge_init(dp_display, dev, encoder); - if (IS_ERR(dp_display->bridge)) { - ret = PTR_ERR(dp_display->bridge); + ret = dp_bridge_init(dp_display, dev, encoder); + if (ret) { DRM_DEV_ERROR(dev->dev, "failed to create dp bridge: %d\n", ret); - dp_display->bridge = NULL; return ret; } - priv->bridges[priv->num_bridges++] = dp_display->bridge; - dp_display->connector = dp_drm_connector_init(dp_display, encoder); if (IS_ERR(dp_display->connector)) { ret = PTR_ERR(dp_display->connector); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 1e9415ab15..f66cdbc357 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -12,6 +12,7 @@ struct msm_dp { struct drm_device *drm_dev; + struct platform_device *pdev; struct device *codec_dev; struct drm_bridge *bridge; struct drm_connector *connector; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index 785d766394..e3bdd7dd4c 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -272,7 +272,7 @@ static const struct drm_bridge_funcs edp_bridge_ops = { .atomic_check = edp_bridge_atomic_check, }; -struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev, +int dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev, struct drm_encoder *encoder) { int rc; @@ -281,7 +281,7 @@ struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device * dp_bridge = devm_kzalloc(dev->dev, sizeof(*dp_bridge), GFP_KERNEL); if (!dp_bridge) - return ERR_PTR(-ENOMEM); + return -ENOMEM; dp_bridge->dp_display = dp_display; @@ -307,14 +307,18 @@ struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device * DRM_BRIDGE_OP_MODES; } - drm_bridge_add(bridge); + rc = devm_drm_bridge_add(dev->dev, bridge); + if (rc) { + DRM_ERROR("failed to add bridge, rc=%d\n", rc); + + return rc; + } rc = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (rc) { DRM_ERROR("failed to attach bridge, rc=%d\n", rc); - drm_bridge_remove(bridge); - return ERR_PTR(rc); + return rc; } if (dp_display->next_bridge) { @@ -323,12 +327,13 @@ struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device * 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 rc; } } - return bridge; + dp_display->bridge = bridge; + + return 0; } /* connector initialization */ @@ -340,6 +345,9 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct dr if (IS_ERR(connector)) return connector; + if (!dp_display->is_edp) + drm_connector_attach_dp_subconnector_property(connector); + drm_connector_attach_encoder(connector, encoder); return connector; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index afe79b85e1..b3d684db23 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -20,7 +20,7 @@ struct msm_dp_bridge { #define to_dp_bridge(x) container_of((x), struct msm_dp_bridge, bridge) struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct drm_encoder *encoder); -struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev, +int dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev, struct drm_encoder *encoder); void dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 6375daaeb9..49dfac1fd1 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -7,6 +7,7 @@ #include <drm/drm_print.h> +#include "dp_reg.h" #include "dp_link.h" #include "dp_panel.h" @@ -712,49 +713,17 @@ end: return ret; } -/** - * dp_link_parse_sink_count() - parses the sink count - * @dp_link: pointer to link module data - * - * Parses the DPCD to check if there is an update to the sink count - * (Byte 0x200), and whether all the sink devices connected have Content - * Protection enabled. - */ -static int dp_link_parse_sink_count(struct dp_link *dp_link) -{ - ssize_t rlen; - bool cp_ready; - - struct dp_link_private *link = container_of(dp_link, - struct dp_link_private, dp_link); - - rlen = drm_dp_dpcd_readb(link->aux, DP_SINK_COUNT, - &link->dp_link.sink_count); - if (rlen < 0) { - DRM_ERROR("sink count read failed. rlen=%zd\n", rlen); - return rlen; - } - - cp_ready = link->dp_link.sink_count & DP_SINK_CP_READY; - - link->dp_link.sink_count = - DP_GET_SINK_COUNT(link->dp_link.sink_count); - - drm_dbg_dp(link->drm_dev, "sink_count = 0x%x, cp_ready = 0x%x\n", - link->dp_link.sink_count, cp_ready); - return 0; -} - static int dp_link_parse_sink_status_field(struct dp_link_private *link) { - int len = 0; + int len; link->prev_sink_count = link->dp_link.sink_count; - len = dp_link_parse_sink_count(&link->dp_link); + len = drm_dp_read_sink_count(link->aux); if (len < 0) { DRM_ERROR("DP parse sink count failed\n"); return len; } + link->dp_link.sink_count = len; len = drm_dp_dpcd_read_link_status(link->aux, link->link_status); @@ -1114,7 +1083,7 @@ int dp_link_process_request(struct dp_link *dp_link) int dp_link_get_colorimetry_config(struct dp_link *dp_link) { - u32 cc; + u32 cc = DP_MISC0_COLORIMERY_CFG_LEGACY_RGB; struct dp_link_private *link; if (!dp_link) { @@ -1128,10 +1097,11 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link) * Unless a video pattern CTS test is ongoing, use RGB_VESA * Only RGB_VESA and RGB_CEA supported for now */ - if (dp_link_is_video_pattern_requested(link)) - cc = link->dp_link.test_video.test_dyn_range; - else - cc = DP_TEST_DYNAMIC_RANGE_VESA; + if (dp_link_is_video_pattern_requested(link)) { + if (link->dp_link.test_video.test_dyn_range & + DP_TEST_DYNAMIC_RANGE_CEA) + cc = DP_MISC0_COLORIMERY_CFG_CEA_RGB; + } return cc; } @@ -1211,6 +1181,9 @@ void dp_link_reset_phy_params_vx_px(struct dp_link *dp_link) u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp) { u32 tbd; + struct dp_link_private *link; + + link = container_of(dp_link, struct dp_link_private, dp_link); /* * Few simplistic rules and assumptions made here: @@ -1228,12 +1201,13 @@ u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp) tbd = DP_TEST_BIT_DEPTH_10; break; default: - tbd = DP_TEST_BIT_DEPTH_UNKNOWN; + drm_dbg_dp(link->drm_dev, "bpp=%d not supported, use bpc=8\n", + bpp); + tbd = DP_TEST_BIT_DEPTH_8; break; } - if (tbd != DP_TEST_BIT_DEPTH_UNKNOWN) - tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT); + tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT); return tbd; } diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 86a8e06c7a..127f6af995 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -17,7 +17,6 @@ struct dp_panel_private { struct dp_link *link; struct dp_catalog *catalog; bool panel_on; - bool aux_cfg_update_done; }; static void dp_panel_read_psr_cap(struct dp_panel_private *panel) @@ -43,58 +42,24 @@ static void dp_panel_read_psr_cap(struct dp_panel_private *panel) static int dp_panel_read_dpcd(struct dp_panel *dp_panel) { - int rc = 0; - size_t len; - ssize_t rlen; + int rc; struct dp_panel_private *panel; struct dp_link_info *link_info; - u8 *dpcd, major = 0, minor = 0, temp; - u32 offset = DP_DPCD_REV; + u8 *dpcd, major, minor; + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); dpcd = dp_panel->dpcd; + rc = drm_dp_read_dpcd_caps(panel->aux, dpcd); + if (rc) + return rc; - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); link_info = &dp_panel->link_info; - - rlen = drm_dp_dpcd_read(panel->aux, offset, - dpcd, (DP_RECEIVER_CAP_SIZE + 1)); - if (rlen < (DP_RECEIVER_CAP_SIZE + 1)) { - DRM_ERROR("dpcd read failed, rlen=%zd\n", rlen); - if (rlen == -ETIMEDOUT) - rc = rlen; - else - rc = -EINVAL; - - goto end; - } - - temp = dpcd[DP_TRAINING_AUX_RD_INTERVAL]; - - /* check for EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT */ - if (temp & BIT(7)) { - drm_dbg_dp(panel->drm_dev, - "using EXTENDED_RECEIVER_CAPABILITY_FIELD\n"); - offset = DPRX_EXTENDED_DPCD_FIELD; - } - - rlen = drm_dp_dpcd_read(panel->aux, offset, - dpcd, (DP_RECEIVER_CAP_SIZE + 1)); - if (rlen < (DP_RECEIVER_CAP_SIZE + 1)) { - DRM_ERROR("dpcd read failed, rlen=%zd\n", rlen); - if (rlen == -ETIMEDOUT) - rc = rlen; - else - rc = -EINVAL; - - goto end; - } - link_info->revision = dpcd[DP_DPCD_REV]; major = (link_info->revision >> 4) & 0x0f; minor = link_info->revision & 0x0f; - link_info->rate = drm_dp_bw_code_to_link_rate(dpcd[DP_MAX_LINK_RATE]); - link_info->num_lanes = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; + link_info->rate = drm_dp_max_link_rate(dpcd); + link_info->num_lanes = drm_dp_max_lane_count(dpcd); /* Limit data lanes from data-lanes of endpoint property of dtsi */ if (link_info->num_lanes > dp_panel->max_dp_lanes) @@ -111,25 +76,8 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel) if (drm_dp_enhanced_frame_cap(dpcd)) link_info->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING; - dp_panel->dfp_present = dpcd[DP_DOWNSTREAMPORT_PRESENT]; - dp_panel->dfp_present &= DP_DWN_STRM_PORT_PRESENT; - - if (dp_panel->dfp_present && (dpcd[DP_DPCD_REV] > 0x10)) { - dp_panel->ds_port_cnt = dpcd[DP_DOWN_STREAM_PORT_COUNT]; - dp_panel->ds_port_cnt &= DP_PORT_COUNT_MASK; - len = DP_DOWNSTREAM_PORTS * DP_DOWNSTREAM_CAP_SIZE; - - rlen = drm_dp_dpcd_read(panel->aux, - DP_DOWNSTREAM_PORT_0, dp_panel->ds_cap_info, len); - if (rlen < len) { - DRM_ERROR("ds port status failed, rlen=%zd\n", rlen); - rc = -EINVAL; - goto end; - } - } - dp_panel_read_psr_cap(panel); -end: + return rc; } @@ -179,8 +127,8 @@ static int dp_panel_update_modes(struct drm_connector *connector, int dp_panel_read_sink_caps(struct dp_panel *dp_panel, struct drm_connector *connector) { - int rc = 0, bw_code; - int rlen, count; + int rc, bw_code; + int count; struct dp_panel_private *panel; if (!dp_panel || !connector) { @@ -205,20 +153,19 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel, return -EINVAL; } - if (dp_panel->dfp_present) { - rlen = drm_dp_dpcd_read(panel->aux, DP_SINK_COUNT, - &count, 1); - if (rlen == 1) { - count = DP_GET_SINK_COUNT(count); - if (!count) { - DRM_ERROR("no downstream ports connected\n"); - panel->link->sink_count = 0; - rc = -ENOTCONN; - goto end; - } + if (drm_dp_is_branch(dp_panel->dpcd)) { + count = drm_dp_read_sink_count(panel->aux); + if (!count) { + panel->link->sink_count = 0; + return -ENOTCONN; } } + rc = drm_dp_read_downstream_info(panel->aux, dp_panel->dpcd, + dp_panel->downstream_ports); + if (rc) + return rc; + kfree(dp_panel->edid); dp_panel->edid = NULL; @@ -233,19 +180,6 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel, } } - if (panel->aux_cfg_update_done) { - drm_dbg_dp(panel->drm_dev, - "read DPCD with updated AUX config\n"); - rc = dp_panel_read_dpcd(dp_panel); - bw_code = drm_dp_link_rate_to_bw_code(dp_panel->link_info.rate); - if (rc || !is_link_rate_valid(bw_code) || - !is_lane_count_valid(dp_panel->link_info.num_lanes) - || (bw_code > dp_panel->max_bw_code)) { - DRM_ERROR("read dpcd failed %d\n", rc); - return rc; - } - panel->aux_cfg_update_done = false; - } end: return rc; } @@ -473,7 +407,6 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in) dp_panel = &panel->dp_panel; dp_panel->max_bw_code = DP_LINK_BW_8_1; - panel->aux_cfg_update_done = false; return dp_panel; } diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index ed1030e17e..a0dfc579c5 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -13,11 +13,6 @@ struct edid; -#define DPRX_EXTENDED_DPCD_FIELD 0x2200 - -#define DP_DOWNSTREAM_PORTS 4 -#define DP_DOWNSTREAM_CAP_SIZE 4 - struct dp_display_mode { struct drm_display_mode drm_mode; u32 capabilities; @@ -40,10 +35,8 @@ struct dp_panel_psr { struct dp_panel { /* dpcd raw data */ - u8 dpcd[DP_RECEIVER_CAP_SIZE + 1]; - u8 ds_cap_info[DP_DOWNSTREAM_PORTS * DP_DOWNSTREAM_CAP_SIZE]; - u32 ds_port_cnt; - u32 dfp_present; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; + u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; struct dp_link_info link_info; struct drm_dp_desc desc; diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index ea85a691e7..78785ed4b4 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -143,6 +143,9 @@ #define DP_MISC0_COLORIMETRY_CFG_SHIFT (0x00000001) #define DP_MISC0_TEST_BITS_DEPTH_SHIFT (0x00000005) +#define DP_MISC0_COLORIMERY_CFG_LEGACY_RGB (0) +#define DP_MISC0_COLORIMERY_CFG_CEA_RGB (0x04) + #define REG_DP_VALID_BOUNDARY (0x00000030) #define REG_DP_VALID_BOUNDARY_2 (0x00000034) diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 32f965bacd..c6bd7bf156 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -17,6 +17,11 @@ struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi) return msm_dsi_host_get_dsc_config(msm_dsi->host); } +bool msm_dsi_wide_bus_enabled(struct msm_dsi *msm_dsi) +{ + return msm_dsi_host_is_wide_bus_enabled(msm_dsi->host); +} + static int dsi_get_phy(struct msm_dsi *msm_dsi) { struct platform_device *pdev = msm_dsi->pdev; @@ -162,14 +167,12 @@ static int dsi_dev_probe(struct platform_device *pdev) return 0; } -static int dsi_dev_remove(struct platform_device *pdev) +static void dsi_dev_remove(struct platform_device *pdev) { struct msm_dsi *msm_dsi = platform_get_drvdata(pdev); DBG(""); dsi_destroy(msm_dsi); - - return 0; } static const struct of_device_id dt_match[] = { @@ -188,7 +191,7 @@ static const struct dev_pm_ops dsi_pm_ops = { static struct platform_driver dsi_driver = { .probe = dsi_dev_probe, - .remove = dsi_dev_remove, + .remove_new = dsi_dev_remove, .driver = { .name = "msm_dsi", .of_match_table = dt_match, @@ -213,20 +216,14 @@ void __exit msm_dsi_unregister(void) int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, struct drm_encoder *encoder) { - struct msm_drm_private *priv = dev->dev_private; int ret; - if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) { - DRM_DEV_ERROR(dev->dev, "too many bridges\n"); - return -ENOSPC; - } - msm_dsi->dev = dev; ret = msm_dsi_host_modeset_init(msm_dsi->host, dev); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to modeset init host: %d\n", ret); - goto fail; + return ret; } if (msm_dsi_is_bonded_dsi(msm_dsi) && @@ -240,32 +237,20 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, msm_dsi->encoder = encoder; - msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id); - if (IS_ERR(msm_dsi->bridge)) { - ret = PTR_ERR(msm_dsi->bridge); + ret = msm_dsi_manager_bridge_init(msm_dsi); + if (ret) { DRM_DEV_ERROR(dev->dev, "failed to create dsi bridge: %d\n", ret); - msm_dsi->bridge = NULL; - goto fail; + return ret; } ret = msm_dsi_manager_ext_bridge_init(msm_dsi->id); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to create dsi connector: %d\n", ret); - goto fail; + return ret; } - priv->bridges[priv->num_bridges++] = msm_dsi->bridge; - return 0; -fail: - /* bridge/connector are normally destroyed by drm: */ - if (msm_dsi->bridge) { - msm_dsi_manager_bridge_destroy(msm_dsi->bridge); - msm_dsi->bridge = NULL; - } - - return ret; } void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 3b46617a59..28379b1af6 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -56,8 +56,7 @@ struct msm_dsi { }; /* dsi manager */ -struct drm_bridge *msm_dsi_manager_bridge_init(u8 id); -void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge); +int msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi); int msm_dsi_manager_ext_bridge_init(u8 id); int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg); bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len); @@ -135,6 +134,7 @@ int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi); void msm_dsi_host_snapshot(struct msm_disp_state *disp_state, struct mipi_dsi_host *host); void msm_dsi_host_test_pattern_en(struct mipi_dsi_host *host); struct drm_dsc_config *msm_dsi_host_get_dsc_config(struct mipi_dsi_host *host); +bool msm_dsi_host_is_wide_bus_enabled(struct mipi_dsi_host *host); /* dsi phy */ struct msm_dsi_phy; diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h index a4a1546011..2a7d980e12 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h @@ -664,6 +664,7 @@ static inline uint32_t DSI_CMD_MODE_MDP_CTRL2_INPUT_RGB_SWAP(enum dsi_rgb_swap v return ((val) << DSI_CMD_MODE_MDP_CTRL2_INPUT_RGB_SWAP__SHIFT) & DSI_CMD_MODE_MDP_CTRL2_INPUT_RGB_SWAP__MASK; } #define DSI_CMD_MODE_MDP_CTRL2_BURST_MODE 0x00010000 +#define DSI_CMD_MODE_MDP_CTRL2_DATABUS_WIDEN 0x00100000 #define REG_DSI_CMD_MODE_MDP_STREAM2_CTRL 0x000001b8 #define DSI_CMD_MODE_MDP_STREAM2_CTRL_DATA_TYPE__MASK 0x0000003f diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 470866896b..deeecdfd6c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -711,6 +711,15 @@ static void dsi_ctrl_disable(struct msm_dsi_host *msm_host) dsi_write(msm_host, REG_DSI_CTRL, 0); } +bool msm_dsi_host_is_wide_bus_enabled(struct mipi_dsi_host *host) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + return msm_host->dsc && + (msm_host->cfg_hnd->major == MSM_DSI_VER_MAJOR_6G && + msm_host->cfg_hnd->minor >= MSM_DSI_6G_VER_MINOR_V2_5_0); +} + static void dsi_ctrl_enable(struct msm_dsi_host *msm_host, struct msm_dsi_phy_shared_timings *phy_shared_timings, struct msm_dsi_phy *phy) { @@ -754,10 +763,16 @@ static void dsi_ctrl_enable(struct msm_dsi_host *msm_host, data |= DSI_CMD_CFG1_INSERT_DCS_COMMAND; dsi_write(msm_host, REG_DSI_CMD_CFG1, data); - if (msm_host->cfg_hnd->major == MSM_DSI_VER_MAJOR_6G && - msm_host->cfg_hnd->minor >= MSM_DSI_6G_VER_MINOR_V1_3) { + if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) { data = dsi_read(msm_host, REG_DSI_CMD_MODE_MDP_CTRL2); - data |= DSI_CMD_MODE_MDP_CTRL2_BURST_MODE; + + if (cfg_hnd->minor >= MSM_DSI_6G_VER_MINOR_V1_3) + data |= DSI_CMD_MODE_MDP_CTRL2_BURST_MODE; + + /* TODO: Allow for video-mode support once tested/fixed */ + if (msm_dsi_host_is_wide_bus_enabled(&msm_host->base)) + data |= DSI_CMD_MODE_MDP_CTRL2_DATABUS_WIDEN; + dsi_write(msm_host, REG_DSI_CMD_MODE_MDP_CTRL2, data); } } @@ -895,6 +910,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) u32 hdisplay = mode->hdisplay; u32 wc; int ret; + bool wide_bus_enabled = msm_dsi_host_is_wide_bus_enabled(&msm_host->base); DBG(""); @@ -915,6 +931,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) if (msm_host->dsc) { struct drm_dsc_config *dsc = msm_host->dsc; + u32 bytes_per_pclk; /* update dsc params with timing params */ if (!dsc || !mode->hdisplay || !mode->vdisplay) { @@ -938,7 +955,13 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) * pulse width same */ h_total -= hdisplay; - hdisplay = DIV_ROUND_UP(msm_dsc_get_bytes_per_line(msm_host->dsc), 3); + if (wide_bus_enabled && !(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO)) + bytes_per_pclk = 6; + else + bytes_per_pclk = 3; + + hdisplay = DIV_ROUND_UP(msm_dsc_get_bytes_per_line(msm_host->dsc), bytes_per_pclk); + h_total += hdisplay; ha_end = ha_start + hdisplay; } diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 28b8012a21..896f369fdd 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -466,9 +466,8 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = { }; /* initialize bridge */ -struct drm_bridge *msm_dsi_manager_bridge_init(u8 id) +int msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi) { - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct drm_bridge *bridge = NULL; struct dsi_bridge *dsi_bridge; struct drm_encoder *encoder; @@ -476,31 +475,27 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id) dsi_bridge = devm_kzalloc(msm_dsi->dev->dev, sizeof(*dsi_bridge), GFP_KERNEL); - if (!dsi_bridge) { - ret = -ENOMEM; - goto fail; - } + if (!dsi_bridge) + return -ENOMEM; - dsi_bridge->id = id; + dsi_bridge->id = msm_dsi->id; encoder = msm_dsi->encoder; bridge = &dsi_bridge->base; bridge->funcs = &dsi_mgr_bridge_funcs; - drm_bridge_add(bridge); + ret = devm_drm_bridge_add(msm_dsi->dev->dev, bridge); + if (ret) + return ret; ret = drm_bridge_attach(encoder, bridge, NULL, 0); if (ret) - goto fail; + return ret; - return bridge; + msm_dsi->bridge = bridge; -fail: - if (bridge) - msm_dsi_manager_bridge_destroy(bridge); - - return ERR_PTR(ret); + return 0; } int msm_dsi_manager_ext_bridge_init(u8 id) @@ -557,11 +552,6 @@ int msm_dsi_manager_ext_bridge_init(u8 id) return 0; } -void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge) -{ - drm_bridge_remove(bridge); -} - int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg) { struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index b6314bb66d..e49ebd9f63 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -691,6 +691,10 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(phy->ahb_clk), "Unable to get ahb clk\n"); + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + /* PLL init will call into clk_register which requires * register access, so we need to enable power and ahb clock. */ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 60509fb397..c8ebd75176 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -160,24 +160,16 @@ fail: int msm_hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev, struct drm_encoder *encoder) { - struct msm_drm_private *priv = dev->dev_private; int ret; - if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) { - DRM_DEV_ERROR(dev->dev, "too many bridges\n"); - return -ENOSPC; - } - hdmi->dev = dev; hdmi->encoder = encoder; hdmi_audio_infoframe_init(&hdmi->audio.infoframe); - hdmi->bridge = msm_hdmi_bridge_init(hdmi); - if (IS_ERR(hdmi->bridge)) { - ret = PTR_ERR(hdmi->bridge); + ret = msm_hdmi_bridge_init(hdmi); + if (ret) { DRM_DEV_ERROR(dev->dev, "failed to create HDMI bridge: %d\n", ret); - hdmi->bridge = NULL; goto fail; } @@ -215,16 +207,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, goto fail; } - priv->bridges[priv->num_bridges++] = hdmi->bridge; - return 0; fail: - /* bridge is normally destroyed by drm: */ - if (hdmi->bridge) { - msm_hdmi_bridge_destroy(hdmi->bridge); - hdmi->bridge = NULL; - } if (hdmi->connector) { hdmi->connector->funcs->destroy(hdmi->connector); hdmi->connector = NULL; @@ -395,6 +380,9 @@ static void msm_hdmi_unbind(struct device *dev, struct device *master, if (priv->hdmi->audio_pdev) platform_device_unregister(priv->hdmi->audio_pdev); + if (priv->hdmi->bridge) + msm_hdmi_hpd_disable(priv->hdmi); + msm_hdmi_destroy(priv->hdmi); priv->hdmi = NULL; } @@ -551,15 +539,13 @@ err_put_phy: return ret; } -static int msm_hdmi_dev_remove(struct platform_device *pdev) +static void msm_hdmi_dev_remove(struct platform_device *pdev) { struct hdmi *hdmi = dev_get_drvdata(&pdev->dev); component_del(&pdev->dev, &msm_hdmi_ops); msm_hdmi_put_phy(hdmi); - - return 0; } static const struct of_device_id msm_hdmi_dt_match[] = { @@ -574,7 +560,7 @@ static const struct of_device_id msm_hdmi_dt_match[] = { static struct platform_driver msm_hdmi_driver = { .probe = msm_hdmi_dev_probe, - .remove = msm_hdmi_dev_remove, + .remove_new = msm_hdmi_dev_remove, .driver = { .name = "hdmi_msm", .of_match_table = msm_hdmi_dt_match, diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index e8dbee5063..ec57864403 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -224,14 +224,13 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate); * hdmi bridge: */ -struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi); -void msm_hdmi_bridge_destroy(struct drm_bridge *bridge); +int msm_hdmi_bridge_init(struct hdmi *hdmi); void msm_hdmi_hpd_irq(struct drm_bridge *bridge); enum drm_connector_status msm_hdmi_bridge_detect( struct drm_bridge *bridge); int msm_hdmi_hpd_enable(struct drm_bridge *bridge); -void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge); +void msm_hdmi_hpd_disable(struct hdmi *hdmi); /* * i2c adapter for ddc: diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 9b1391d27e..f5e01471b0 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -11,14 +11,6 @@ #include "msm_kms.h" #include "hdmi.h" -void msm_hdmi_bridge_destroy(struct drm_bridge *bridge) -{ - struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); - - msm_hdmi_hpd_disable(hdmi_bridge); - drm_bridge_remove(bridge); -} - static void msm_hdmi_power_on(struct drm_bridge *bridge) { struct drm_device *dev = bridge->dev; @@ -317,7 +309,7 @@ msm_hdmi_hotplug_work(struct work_struct *work) } /* initialize bridge */ -struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi) +int msm_hdmi_bridge_init(struct hdmi *hdmi) { struct drm_bridge *bridge = NULL; struct hdmi_bridge *hdmi_bridge; @@ -325,10 +317,8 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi) hdmi_bridge = devm_kzalloc(hdmi->dev->dev, sizeof(*hdmi_bridge), GFP_KERNEL); - if (!hdmi_bridge) { - ret = -ENOMEM; - goto fail; - } + if (!hdmi_bridge) + return -ENOMEM; hdmi_bridge->hdmi = hdmi; INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work); @@ -341,17 +331,15 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi) DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID; - drm_bridge_add(bridge); + ret = devm_drm_bridge_add(hdmi->dev->dev, bridge); + if (ret) + return ret; ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (ret) - goto fail; + return ret; - return bridge; + hdmi->bridge = bridge; -fail: - if (bridge) - msm_hdmi_bridge_destroy(bridge); - - return ERR_PTR(ret); + return 0; } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c index bfa827b479..9ce0ffa354 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c @@ -147,9 +147,8 @@ fail: return ret; } -void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge) +void msm_hdmi_hpd_disable(struct hdmi *hdmi) { - struct hdmi *hdmi = hdmi_bridge->hdmi; const struct hdmi_platform_config *config = hdmi->config; struct device *dev = &hdmi->pdev->dev; int ret; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c index 3e00fb8190..88a3423b7f 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c @@ -177,11 +177,9 @@ static int msm_hdmi_phy_probe(struct platform_device *pdev) return 0; } -static int msm_hdmi_phy_remove(struct platform_device *pdev) +static void msm_hdmi_phy_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct of_device_id msm_hdmi_phy_dt_match[] = { @@ -200,7 +198,7 @@ static const struct of_device_id msm_hdmi_phy_dt_match[] = { static struct platform_driver msm_hdmi_phy_platform_driver = { .probe = msm_hdmi_phy_probe, - .remove = msm_hdmi_phy_remove, + .remove_new = msm_hdmi_phy_remove, .driver = { .name = "msm_hdmi_phy", .of_match_table = msm_hdmi_phy_dt_match, diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c index a0a936f80a..04d304eed2 100644 --- a/drivers/gpu/drm/msm/msm_debugfs.c +++ b/drivers/gpu/drm/msm/msm_debugfs.c @@ -266,6 +266,9 @@ static int msm_fb_show(struct seq_file *m, void *arg) static struct drm_info_list msm_debugfs_list[] = { {"gem", msm_gem_show}, { "mm", msm_mm_show }, +}; + +static struct drm_info_list msm_kms_debugfs_list[] = { { "fb", msm_fb_show }, }; @@ -314,8 +317,13 @@ void msm_debugfs_init(struct drm_minor *minor) debugfs_create_file("gpu", S_IRUSR, minor->debugfs_root, dev, &msm_gpu_fops); - debugfs_create_file("kms", S_IRUSR, minor->debugfs_root, - dev, &msm_kms_fops); + if (priv->kms) { + drm_debugfs_create_files(msm_kms_debugfs_list, + ARRAY_SIZE(msm_kms_debugfs_list), + minor->debugfs_root, minor); + debugfs_create_file("kms", S_IRUSR, minor->debugfs_root, + dev, &msm_kms_fops); + } debugfs_create_u32("hangcheck_period_ms", 0600, minor->debugfs_root, &priv->hangcheck_period); diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 4bd028fa75..3f217b5782 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -7,29 +7,17 @@ #include <linux/dma-mapping.h> #include <linux/fault-inject.h> -#include <linux/kthread.h> #include <linux/of_address.h> -#include <linux/sched/mm.h> #include <linux/uaccess.h> -#include <uapi/linux/sched/types.h> -#include <drm/drm_aperture.h> -#include <drm/drm_bridge.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> #include <drm/drm_ioctl.h> -#include <drm/drm_prime.h> #include <drm/drm_of.h> -#include <drm/drm_vblank.h> -#include "disp/msm_disp_snapshot.h" #include "msm_drv.h" #include "msm_debugfs.h" -#include "msm_fence.h" -#include "msm_gem.h" -#include "msm_gpu.h" #include "msm_kms.h" -#include "msm_mmu.h" #include "adreno/adreno_gpu.h" /* @@ -56,16 +44,6 @@ static void msm_deinit_vram(struct drm_device *ddev); -static const struct drm_mode_config_funcs mode_config_funcs = { - .fb_create = msm_framebuffer_create, - .atomic_check = msm_atomic_check, - .atomic_commit = drm_atomic_helper_commit, -}; - -static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = { - .atomic_commit_tail = msm_atomic_commit_tail, -}; - static char *vram = "16m"; MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU)"); module_param(vram, charp, 0); @@ -83,125 +61,11 @@ DECLARE_FAULT_ATTR(fail_gem_alloc); DECLARE_FAULT_ATTR(fail_gem_iova); #endif -static irqreturn_t msm_irq(int irq, void *arg) -{ - struct drm_device *dev = arg; - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - - BUG_ON(!kms); - - return kms->funcs->irq(kms); -} - -static void msm_irq_preinstall(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - - BUG_ON(!kms); - - kms->funcs->irq_preinstall(kms); -} - -static int msm_irq_postinstall(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - - BUG_ON(!kms); - - if (kms->funcs->irq_postinstall) - return kms->funcs->irq_postinstall(kms); - - return 0; -} - -static int msm_irq_install(struct drm_device *dev, unsigned int irq) -{ - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - int ret; - - if (irq == IRQ_NOTCONNECTED) - return -ENOTCONN; - - msm_irq_preinstall(dev); - - ret = request_irq(irq, msm_irq, 0, dev->driver->name, dev); - if (ret) - return ret; - - kms->irq_requested = true; - - ret = msm_irq_postinstall(dev); - if (ret) { - free_irq(irq, dev); - return ret; - } - - return 0; -} - -static void msm_irq_uninstall(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - - kms->funcs->irq_uninstall(kms); - if (kms->irq_requested) - free_irq(kms->irq, dev); -} - -struct msm_vblank_work { - struct work_struct work; - struct drm_crtc *crtc; - bool enable; - struct msm_drm_private *priv; -}; - -static void vblank_ctrl_worker(struct work_struct *work) -{ - struct msm_vblank_work *vbl_work = container_of(work, - struct msm_vblank_work, work); - struct msm_drm_private *priv = vbl_work->priv; - struct msm_kms *kms = priv->kms; - - if (vbl_work->enable) - kms->funcs->enable_vblank(kms, vbl_work->crtc); - else - kms->funcs->disable_vblank(kms, vbl_work->crtc); - - kfree(vbl_work); -} - -static int vblank_ctrl_queue_work(struct msm_drm_private *priv, - struct drm_crtc *crtc, bool enable) -{ - struct msm_vblank_work *vbl_work; - - vbl_work = kzalloc(sizeof(*vbl_work), GFP_ATOMIC); - if (!vbl_work) - return -ENOMEM; - - INIT_WORK(&vbl_work->work, vblank_ctrl_worker); - - vbl_work->crtc = crtc; - vbl_work->enable = enable; - vbl_work->priv = priv; - - queue_work(priv->wq, &vbl_work->work); - - return 0; -} - static int msm_drm_uninit(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct msm_drm_private *priv = platform_get_drvdata(pdev); struct drm_device *ddev = priv->dev; - struct msm_kms *kms = priv->kms; - int i; /* * Shutdown the hw if we're far enough along where things might be on. @@ -212,7 +76,8 @@ static int msm_drm_uninit(struct device *dev) */ if (ddev->registered) { drm_dev_unregister(ddev); - drm_atomic_helper_shutdown(ddev); + if (priv->kms) + drm_atomic_helper_shutdown(ddev); } /* We must cancel and cleanup any pending vblank enable/disable @@ -222,36 +87,13 @@ static int msm_drm_uninit(struct device *dev) flush_workqueue(priv->wq); - /* clean up event worker threads */ - for (i = 0; i < priv->num_crtcs; i++) { - if (priv->event_thread[i].worker) - kthread_destroy_worker(priv->event_thread[i].worker); - } - msm_gem_shrinker_cleanup(ddev); - drm_kms_helper_poll_fini(ddev); - msm_perf_debugfs_cleanup(priv); msm_rd_debugfs_cleanup(priv); - if (kms) - msm_disp_snapshot_destroy(ddev); - - drm_mode_config_cleanup(ddev); - - for (i = 0; i < priv->num_bridges; i++) - drm_bridge_remove(priv->bridges[i]); - priv->num_bridges = 0; - - if (kms) { - pm_runtime_get_sync(dev); - msm_irq_uninstall(ddev); - pm_runtime_put_sync(dev); - } - - if (kms && kms->funcs) - kms->funcs->destroy(kms); + if (priv->kms) + msm_drm_kms_uninit(dev); msm_deinit_vram(ddev); @@ -265,42 +107,6 @@ static int msm_drm_uninit(struct device *dev) return 0; } -struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev) -{ - struct msm_gem_address_space *aspace; - struct msm_mmu *mmu; - struct device *mdp_dev = dev->dev; - struct device *mdss_dev = mdp_dev->parent; - struct device *iommu_dev; - - /* - * IOMMUs can be a part of MDSS device tree binding, or the - * MDP/DPU device. - */ - if (device_iommu_mapped(mdp_dev)) - iommu_dev = mdp_dev; - else - iommu_dev = mdss_dev; - - mmu = msm_iommu_new(iommu_dev, 0); - if (IS_ERR(mmu)) - return ERR_CAST(mmu); - - if (!mmu) { - drm_info(dev, "no IOMMU, fallback to phys contig buffers for scanout\n"); - return NULL; - } - - aspace = msm_gem_address_space_create(mmu, "mdp_kms", - 0x1000, 0x100000000 - 0x1000); - if (IS_ERR(aspace)) { - dev_err(mdp_dev, "aspace create, error %pe\n", aspace); - mmu->funcs->destroy(mmu); - } - - return aspace; -} - bool msm_use_mmu(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; @@ -406,8 +212,6 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) { struct msm_drm_private *priv = dev_get_drvdata(dev); struct drm_device *ddev; - struct msm_kms *kms; - struct drm_crtc *crtc; int ret; if (drm_firmware_drivers_only()) @@ -444,11 +248,15 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) might_lock(&priv->lru.lock); fs_reclaim_release(GFP_KERNEL); - drm_mode_config_init(ddev); + if (priv->kms_init) { + ret = drmm_mode_config_init(ddev); + if (ret) + goto err_destroy_wq; + } ret = msm_init_vram(ddev); if (ret) - goto err_cleanup_mode_config; + goto err_destroy_wq; dma_set_max_seg_size(dev, UINT_MAX); @@ -457,96 +265,33 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) if (ret) goto err_deinit_vram; - /* the fw fb could be anywhere in memory */ - ret = drm_aperture_remove_framebuffers(drv); + ret = msm_gem_shrinker_init(ddev); if (ret) goto err_msm_uninit; - msm_gem_shrinker_init(ddev); - if (priv->kms_init) { - ret = priv->kms_init(ddev); - if (ret) { - DRM_DEV_ERROR(dev, "failed to load kms\n"); - priv->kms = NULL; + ret = msm_drm_kms_init(dev, drv); + if (ret) goto err_msm_uninit; - } - kms = priv->kms; } else { /* valid only for the dummy headless case, where of_node=NULL */ WARN_ON(dev->of_node); - kms = NULL; - } - - /* Enable normalization of plane zpos */ - ddev->mode_config.normalize_zpos = true; - - if (kms) { - kms->dev = ddev; - ret = kms->funcs->hw_init(kms); - if (ret) { - DRM_DEV_ERROR(dev, "kms hw init failed: %d\n", ret); - goto err_msm_uninit; - } - } - - drm_helper_move_panel_connectors_to_head(ddev); - - ddev->mode_config.funcs = &mode_config_funcs; - ddev->mode_config.helper_private = &mode_config_helper_funcs; - - drm_for_each_crtc(crtc, ddev) { - struct msm_drm_thread *ev_thread; - - /* initialize event thread */ - ev_thread = &priv->event_thread[drm_crtc_index(crtc)]; - ev_thread->dev = ddev; - ev_thread->worker = kthread_create_worker(0, "crtc_event:%d", crtc->base.id); - if (IS_ERR(ev_thread->worker)) { - ret = PTR_ERR(ev_thread->worker); - DRM_DEV_ERROR(dev, "failed to create crtc_event kthread\n"); - ev_thread->worker = NULL; - goto err_msm_uninit; - } - - sched_set_fifo(ev_thread->worker->task); - } - - ret = drm_vblank_init(ddev, priv->num_crtcs); - if (ret < 0) { - DRM_DEV_ERROR(dev, "failed to initialize vblank\n"); - goto err_msm_uninit; - } - - if (kms) { - pm_runtime_get_sync(dev); - ret = msm_irq_install(ddev, kms->irq); - pm_runtime_put_sync(dev); - if (ret < 0) { - DRM_DEV_ERROR(dev, "failed to install IRQ handler\n"); - goto err_msm_uninit; - } + ddev->driver_features &= ~DRIVER_MODESET; + ddev->driver_features &= ~DRIVER_ATOMIC; } ret = drm_dev_register(ddev, 0); if (ret) goto err_msm_uninit; - if (kms) { - ret = msm_disp_snapshot_init(ddev); - if (ret) - DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); - } - drm_mode_config_reset(ddev); - ret = msm_debugfs_late_init(ddev); if (ret) goto err_msm_uninit; - drm_kms_helper_poll_init(ddev); - - if (kms) + if (priv->kms_init) { + drm_kms_helper_poll_init(ddev); msm_fbdev_setup(ddev); + } return 0; @@ -557,8 +302,7 @@ err_msm_uninit: err_deinit_vram: msm_deinit_vram(ddev); -err_cleanup_mode_config: - drm_mode_config_cleanup(ddev); +err_destroy_wq: destroy_workqueue(priv->wq); err_put_dev: drm_dev_put(ddev); @@ -638,28 +382,6 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file) context_close(ctx); } -int msm_crtc_enable_vblank(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - if (!kms) - return -ENXIO; - drm_dbg_vbl(dev, "crtc=%u", crtc->base.id); - return vblank_ctrl_queue_work(priv, crtc, true); -} - -void msm_crtc_disable_vblank(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - if (!kms) - return; - drm_dbg_vbl(dev, "crtc=%u", crtc->base.id); - vblank_ctrl_queue_work(priv, crtc, false); -} - /* * DRM ioctls: */ @@ -1102,33 +824,6 @@ static const struct drm_driver msm_driver = { .patchlevel = MSM_VERSION_PATCHLEVEL, }; -int msm_pm_prepare(struct device *dev) -{ - struct msm_drm_private *priv = dev_get_drvdata(dev); - struct drm_device *ddev = priv ? priv->dev : NULL; - - if (!priv || !priv->kms) - return 0; - - return drm_mode_config_helper_suspend(ddev); -} - -void msm_pm_complete(struct device *dev) -{ - struct msm_drm_private *priv = dev_get_drvdata(dev); - struct drm_device *ddev = priv ? priv->dev : NULL; - - if (!priv || !priv->kms) - return; - - drm_mode_config_helper_resume(ddev); -} - -static const struct dev_pm_ops msm_pm_ops = { - .prepare = msm_pm_prepare, - .complete = msm_pm_complete, -}; - /* * Componentized driver support: */ @@ -1230,7 +925,8 @@ const struct component_master_ops msm_drm_ops = { }; int msm_drv_probe(struct device *master_dev, - int (*kms_init)(struct drm_device *dev)) + int (*kms_init)(struct drm_device *dev), + struct msm_kms *kms) { struct msm_drm_private *priv; struct component_match *match = NULL; @@ -1240,6 +936,7 @@ int msm_drv_probe(struct device *master_dev, if (!priv) return -ENOMEM; + priv->kms = kms; priv->kms_init = kms_init; dev_set_drvdata(master_dev, priv); @@ -1275,39 +972,19 @@ int msm_drv_probe(struct device *master_dev, static int msm_pdev_probe(struct platform_device *pdev) { - return msm_drv_probe(&pdev->dev, NULL); + return msm_drv_probe(&pdev->dev, NULL, NULL); } -static int msm_pdev_remove(struct platform_device *pdev) +static void msm_pdev_remove(struct platform_device *pdev) { component_master_del(&pdev->dev, &msm_drm_ops); - - return 0; -} - -void msm_drv_shutdown(struct platform_device *pdev) -{ - struct msm_drm_private *priv = platform_get_drvdata(pdev); - struct drm_device *drm = priv ? priv->dev : NULL; - - /* - * Shutdown the hw if we're far enough along where things might be on. - * If we run this too early, we'll end up panicking in any variety of - * places. Since we don't register the drm device until late in - * msm_drm_init, drm_dev->registered is used as an indicator that the - * shutdown will be successful. - */ - if (drm && drm->registered && priv->kms) - drm_atomic_helper_shutdown(drm); } static struct platform_driver msm_platform_driver = { .probe = msm_pdev_probe, - .remove = msm_pdev_remove, - .shutdown = msm_drv_shutdown, + .remove_new = msm_pdev_remove, .driver = { .name = "msm", - .pm = &msm_pm_ops, }, }; diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 02fd6c7d0b..cd5bf658df 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -206,9 +206,6 @@ struct msm_drm_private { struct msm_drm_thread event_thread[MAX_CRTCS]; - unsigned int num_bridges; - struct drm_bridge *bridges[MAX_BRIDGES]; - /* VRAM carveout, used when no IOMMU: */ struct { unsigned long size; @@ -221,7 +218,7 @@ struct msm_drm_private { } vram; struct notifier_block vmap_notifier; - struct shrinker shrinker; + struct shrinker *shrinker; struct drm_atomic_state *pm_state; @@ -283,7 +280,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, unsigned long msm_gem_shrinker_shrink(struct drm_device *dev, unsigned long nr_to_scan); #endif -void msm_gem_shrinker_init(struct drm_device *dev); +int msm_gem_shrinker_init(struct drm_device *dev); void msm_gem_shrinker_cleanup(struct drm_device *dev); struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj); @@ -343,6 +340,7 @@ void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi); bool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi); bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi); +bool msm_dsi_wide_bus_enabled(struct msm_dsi *msm_dsi); struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi); #else static inline void __init msm_dsi_register(void) @@ -372,6 +370,10 @@ static inline bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi) { return false; } +static inline bool msm_dsi_wide_bus_enabled(struct msm_dsi *msm_dsi) +{ + return false; +} static inline struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi) { @@ -561,12 +563,13 @@ static inline unsigned long timeout_to_jiffies(const ktime_t *timeout) extern const struct component_master_ops msm_drm_ops; -int msm_pm_prepare(struct device *dev); -void msm_pm_complete(struct device *dev); +int msm_kms_pm_prepare(struct device *dev); +void msm_kms_pm_complete(struct device *dev); int msm_drv_probe(struct device *dev, - int (*kms_init)(struct drm_device *dev)); -void msm_drv_shutdown(struct platform_device *pdev); + int (*kms_init)(struct drm_device *dev), + struct msm_kms *kms); +void msm_kms_shutdown(struct platform_device *pdev); #endif /* __MSM_DRV_H__ */ diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c index 5f68e31a3e..0915f3b687 100644 --- a/drivers/gpu/drm/msm/msm_gem_prime.c +++ b/drivers/gpu/drm/msm/msm_gem_prime.c @@ -26,7 +26,7 @@ int msm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map) { void *vaddr; - vaddr = msm_gem_get_vaddr(obj); + vaddr = msm_gem_get_vaddr_locked(obj); if (IS_ERR(vaddr)) return PTR_ERR(vaddr); iosys_map_set_vaddr(map, vaddr); @@ -36,7 +36,7 @@ int msm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map) void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map) { - msm_gem_put_vaddr(obj); + msm_gem_put_vaddr_locked(obj); } struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index f38296ad87..5a7d48c02c 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c @@ -34,8 +34,7 @@ static bool can_block(struct shrink_control *sc) static unsigned long msm_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) { - struct msm_drm_private *priv = - container_of(shrinker, struct msm_drm_private, shrinker); + struct msm_drm_private *priv = shrinker->private_data; unsigned count = priv->lru.dontneed.count; if (can_swap()) @@ -100,8 +99,7 @@ active_evict(struct drm_gem_object *obj) static unsigned long msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) { - struct msm_drm_private *priv = - container_of(shrinker, struct msm_drm_private, shrinker); + struct msm_drm_private *priv = shrinker->private_data; struct { struct drm_gem_lru *lru; bool (*shrink)(struct drm_gem_object *obj); @@ -148,10 +146,11 @@ msm_gem_shrinker_shrink(struct drm_device *dev, unsigned long nr_to_scan) struct shrink_control sc = { .nr_to_scan = nr_to_scan, }; - int ret; + unsigned long ret = SHRINK_STOP; fs_reclaim_acquire(GFP_KERNEL); - ret = msm_gem_shrinker_scan(&priv->shrinker, &sc); + if (priv->shrinker) + ret = msm_gem_shrinker_scan(priv->shrinker, &sc); fs_reclaim_release(GFP_KERNEL); return ret; @@ -210,16 +209,24 @@ msm_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr) * * This function registers and sets up the msm shrinker. */ -void msm_gem_shrinker_init(struct drm_device *dev) +int msm_gem_shrinker_init(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; - priv->shrinker.count_objects = msm_gem_shrinker_count; - priv->shrinker.scan_objects = msm_gem_shrinker_scan; - priv->shrinker.seeks = DEFAULT_SEEKS; - WARN_ON(register_shrinker(&priv->shrinker, "drm-msm_gem")); + + priv->shrinker = shrinker_alloc(0, "drm-msm_gem"); + if (!priv->shrinker) + return -ENOMEM; + + priv->shrinker->count_objects = msm_gem_shrinker_count; + priv->shrinker->scan_objects = msm_gem_shrinker_scan; + priv->shrinker->private_data = priv; + + shrinker_register(priv->shrinker); priv->vmap_notifier.notifier_call = msm_gem_shrinker_vmap; WARN_ON(register_vmap_purge_notifier(&priv->vmap_notifier)); + + return 0; } /** @@ -232,8 +239,8 @@ void msm_gem_shrinker_cleanup(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; - if (priv->shrinker.nr_deferred) { + if (priv->shrinker) { WARN_ON(unregister_vmap_purge_notifier(&priv->vmap_notifier)); - unregister_shrinker(&priv->shrinker); + shrinker_free(priv->shrinker); } } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 7f64c66673..5c10b559a5 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -749,12 +749,14 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) struct msm_ringbuffer *ring = submit->ring; unsigned long flags; - pm_runtime_get_sync(&gpu->pdev->dev); + WARN_ON(!mutex_is_locked(&gpu->lock)); - mutex_lock(&gpu->lock); + pm_runtime_get_sync(&gpu->pdev->dev); msm_gpu_hw_init(gpu); + submit->seqno = submit->hw_fence->seqno; + update_sw_cntrs(gpu); /* @@ -779,11 +781,8 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) gpu->funcs->submit(gpu, submit); gpu->cur_ctx_seqno = submit->queue->ctx->seqno; - hangcheck_timer_reset(gpu); - - mutex_unlock(&gpu->lock); - pm_runtime_put(&gpu->pdev->dev); + hangcheck_timer_reset(gpu); } /* diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 5cc8d358cc..d5512037c3 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -21,6 +21,8 @@ struct msm_iommu_pagetable { struct msm_mmu base; struct msm_mmu *parent; struct io_pgtable_ops *pgtbl_ops; + const struct iommu_flush_ops *tlb; + struct device *iommu_dev; unsigned long pgsize_bitmap; /* Bitmap of page sizes in use */ phys_addr_t ttbr; u32 asid; @@ -201,11 +203,33 @@ static const struct msm_mmu_funcs pagetable_funcs = { static void msm_iommu_tlb_flush_all(void *cookie) { + struct msm_iommu_pagetable *pagetable = cookie; + struct adreno_smmu_priv *adreno_smmu; + + if (!pm_runtime_get_if_in_use(pagetable->iommu_dev)) + return; + + adreno_smmu = dev_get_drvdata(pagetable->parent->dev); + + pagetable->tlb->tlb_flush_all((void *)adreno_smmu->cookie); + + pm_runtime_put_autosuspend(pagetable->iommu_dev); } static void msm_iommu_tlb_flush_walk(unsigned long iova, size_t size, size_t granule, void *cookie) { + struct msm_iommu_pagetable *pagetable = cookie; + struct adreno_smmu_priv *adreno_smmu; + + if (!pm_runtime_get_if_in_use(pagetable->iommu_dev)) + return; + + adreno_smmu = dev_get_drvdata(pagetable->parent->dev); + + pagetable->tlb->tlb_flush_walk(iova, size, granule, (void *)adreno_smmu->cookie); + + pm_runtime_put_autosuspend(pagetable->iommu_dev); } static void msm_iommu_tlb_add_page(struct iommu_iotlb_gather *gather, @@ -213,7 +237,7 @@ static void msm_iommu_tlb_add_page(struct iommu_iotlb_gather *gather, { } -static const struct iommu_flush_ops null_tlb_ops = { +static const struct iommu_flush_ops tlb_ops = { .tlb_flush_all = msm_iommu_tlb_flush_all, .tlb_flush_walk = msm_iommu_tlb_flush_walk, .tlb_add_page = msm_iommu_tlb_add_page, @@ -254,10 +278,10 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent) /* The incoming cfg will have the TTBR1 quirk enabled */ ttbr0_cfg.quirks &= ~IO_PGTABLE_QUIRK_ARM_TTBR1; - ttbr0_cfg.tlb = &null_tlb_ops; + ttbr0_cfg.tlb = &tlb_ops; pagetable->pgtbl_ops = alloc_io_pgtable_ops(ARM_64_LPAE_S1, - &ttbr0_cfg, iommu->domain); + &ttbr0_cfg, pagetable); if (!pagetable->pgtbl_ops) { kfree(pagetable); @@ -279,6 +303,8 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent) /* Needed later for TLB flush */ pagetable->parent = parent; + pagetable->tlb = ttbr1_cfg->tlb; + pagetable->iommu_dev = ttbr1_cfg->iommu_dev; pagetable->pgsize_bitmap = ttbr0_cfg.pgsize_bitmap; pagetable->ttbr = ttbr0_cfg.arm_lpae_s1_cfg.ttbr; diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c new file mode 100644 index 0000000000..84c21ec2ce --- /dev/null +++ b/drivers/gpu/drm/msm/msm_kms.c @@ -0,0 +1,345 @@ +// 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 <robdclark@gmail.com> + */ + +#include <linux/kthread.h> +#include <linux/sched/mm.h> +#include <uapi/linux/sched/types.h> + +#include <drm/drm_aperture.h> +#include <drm/drm_drv.h> +#include <drm/drm_mode_config.h> +#include <drm/drm_vblank.h> + +#include "disp/msm_disp_snapshot.h" +#include "msm_drv.h" +#include "msm_gem.h" +#include "msm_kms.h" +#include "msm_mmu.h" + +static const struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = msm_framebuffer_create, + .atomic_check = msm_atomic_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = { + .atomic_commit_tail = msm_atomic_commit_tail, +}; + +static irqreturn_t msm_irq(int irq, void *arg) +{ + struct drm_device *dev = arg; + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + BUG_ON(!kms); + + return kms->funcs->irq(kms); +} + +static void msm_irq_preinstall(struct drm_device *dev) +{ + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + BUG_ON(!kms); + + kms->funcs->irq_preinstall(kms); +} + +static int msm_irq_postinstall(struct drm_device *dev) +{ + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + BUG_ON(!kms); + + if (kms->funcs->irq_postinstall) + return kms->funcs->irq_postinstall(kms); + + return 0; +} + +static int msm_irq_install(struct drm_device *dev, unsigned int irq) +{ + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + int ret; + + if (irq == IRQ_NOTCONNECTED) + return -ENOTCONN; + + msm_irq_preinstall(dev); + + ret = request_irq(irq, msm_irq, 0, dev->driver->name, dev); + if (ret) + return ret; + + kms->irq_requested = true; + + ret = msm_irq_postinstall(dev); + if (ret) { + free_irq(irq, dev); + return ret; + } + + return 0; +} + +static void msm_irq_uninstall(struct drm_device *dev) +{ + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + kms->funcs->irq_uninstall(kms); + if (kms->irq_requested) + free_irq(kms->irq, dev); +} + +struct msm_vblank_work { + struct work_struct work; + struct drm_crtc *crtc; + bool enable; + struct msm_drm_private *priv; +}; + +static void vblank_ctrl_worker(struct work_struct *work) +{ + struct msm_vblank_work *vbl_work = container_of(work, + struct msm_vblank_work, work); + struct msm_drm_private *priv = vbl_work->priv; + struct msm_kms *kms = priv->kms; + + if (vbl_work->enable) + kms->funcs->enable_vblank(kms, vbl_work->crtc); + else + kms->funcs->disable_vblank(kms, vbl_work->crtc); + + kfree(vbl_work); +} + +static int vblank_ctrl_queue_work(struct msm_drm_private *priv, + struct drm_crtc *crtc, bool enable) +{ + struct msm_vblank_work *vbl_work; + + vbl_work = kzalloc(sizeof(*vbl_work), GFP_ATOMIC); + if (!vbl_work) + return -ENOMEM; + + INIT_WORK(&vbl_work->work, vblank_ctrl_worker); + + vbl_work->crtc = crtc; + vbl_work->enable = enable; + vbl_work->priv = priv; + + queue_work(priv->wq, &vbl_work->work); + + return 0; +} + +int msm_crtc_enable_vblank(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + if (!kms) + return -ENXIO; + drm_dbg_vbl(dev, "crtc=%u", crtc->base.id); + return vblank_ctrl_queue_work(priv, crtc, true); +} + +void msm_crtc_disable_vblank(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + if (!kms) + return; + drm_dbg_vbl(dev, "crtc=%u", crtc->base.id); + vblank_ctrl_queue_work(priv, crtc, false); +} + +struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev) +{ + struct msm_gem_address_space *aspace; + struct msm_mmu *mmu; + struct device *mdp_dev = dev->dev; + struct device *mdss_dev = mdp_dev->parent; + struct device *iommu_dev; + + /* + * IOMMUs can be a part of MDSS device tree binding, or the + * MDP/DPU device. + */ + if (device_iommu_mapped(mdp_dev)) + iommu_dev = mdp_dev; + else + iommu_dev = mdss_dev; + + mmu = msm_iommu_new(iommu_dev, 0); + if (IS_ERR(mmu)) + return ERR_CAST(mmu); + + if (!mmu) { + drm_info(dev, "no IOMMU, fallback to phys contig buffers for scanout\n"); + return NULL; + } + + aspace = msm_gem_address_space_create(mmu, "mdp_kms", + 0x1000, 0x100000000 - 0x1000); + if (IS_ERR(aspace)) { + dev_err(mdp_dev, "aspace create, error %pe\n", aspace); + mmu->funcs->destroy(mmu); + } + + return aspace; +} + +void msm_drm_kms_uninit(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct msm_drm_private *priv = platform_get_drvdata(pdev); + struct drm_device *ddev = priv->dev; + struct msm_kms *kms = priv->kms; + int i; + + BUG_ON(!kms); + + /* clean up event worker threads */ + for (i = 0; i < priv->num_crtcs; i++) { + if (priv->event_thread[i].worker) + kthread_destroy_worker(priv->event_thread[i].worker); + } + + drm_kms_helper_poll_fini(ddev); + + msm_disp_snapshot_destroy(ddev); + + pm_runtime_get_sync(dev); + msm_irq_uninstall(ddev); + pm_runtime_put_sync(dev); + + if (kms && kms->funcs) + kms->funcs->destroy(kms); +} + +int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) +{ + struct msm_drm_private *priv = dev_get_drvdata(dev); + struct drm_device *ddev = priv->dev; + struct msm_kms *kms = priv->kms; + struct drm_crtc *crtc; + int ret; + + /* the fw fb could be anywhere in memory */ + ret = drm_aperture_remove_framebuffers(drv); + if (ret) + return ret; + + ret = priv->kms_init(ddev); + if (ret) { + DRM_DEV_ERROR(dev, "failed to load kms\n"); + priv->kms = NULL; + return ret; + } + + /* Enable normalization of plane zpos */ + ddev->mode_config.normalize_zpos = true; + + ddev->mode_config.funcs = &mode_config_funcs; + ddev->mode_config.helper_private = &mode_config_helper_funcs; + + kms->dev = ddev; + ret = kms->funcs->hw_init(kms); + if (ret) { + DRM_DEV_ERROR(dev, "kms hw init failed: %d\n", ret); + goto err_msm_uninit; + } + + drm_helper_move_panel_connectors_to_head(ddev); + + drm_for_each_crtc(crtc, ddev) { + struct msm_drm_thread *ev_thread; + + /* initialize event thread */ + ev_thread = &priv->event_thread[drm_crtc_index(crtc)]; + ev_thread->dev = ddev; + ev_thread->worker = kthread_create_worker(0, "crtc_event:%d", crtc->base.id); + if (IS_ERR(ev_thread->worker)) { + ret = PTR_ERR(ev_thread->worker); + DRM_DEV_ERROR(dev, "failed to create crtc_event kthread\n"); + ev_thread->worker = NULL; + goto err_msm_uninit; + } + + sched_set_fifo(ev_thread->worker->task); + } + + ret = drm_vblank_init(ddev, priv->num_crtcs); + if (ret < 0) { + DRM_DEV_ERROR(dev, "failed to initialize vblank\n"); + goto err_msm_uninit; + } + + pm_runtime_get_sync(dev); + ret = msm_irq_install(ddev, kms->irq); + pm_runtime_put_sync(dev); + if (ret < 0) { + DRM_DEV_ERROR(dev, "failed to install IRQ handler\n"); + goto err_msm_uninit; + } + + ret = msm_disp_snapshot_init(ddev); + if (ret) + DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); + + drm_mode_config_reset(ddev); + + return 0; + +err_msm_uninit: + return ret; +} + +int msm_kms_pm_prepare(struct device *dev) +{ + struct msm_drm_private *priv = dev_get_drvdata(dev); + struct drm_device *ddev = priv ? priv->dev : NULL; + + if (!priv || !priv->kms) + return 0; + + return drm_mode_config_helper_suspend(ddev); +} + +void msm_kms_pm_complete(struct device *dev) +{ + struct msm_drm_private *priv = dev_get_drvdata(dev); + struct drm_device *ddev = priv ? priv->dev : NULL; + + if (!priv || !priv->kms) + return; + + drm_mode_config_helper_resume(ddev); +} + +void msm_kms_shutdown(struct platform_device *pdev) +{ + struct msm_drm_private *priv = platform_get_drvdata(pdev); + struct drm_device *drm = priv ? priv->dev : NULL; + + /* + * Shutdown the hw if we're far enough along where things might be on. + * If we run this too early, we'll end up panicking in any variety of + * places. Since we don't register the drm device until late in + * msm_drm_init, drm_dev->registered is used as an indicator that the + * shutdown will be successful. + */ + if (drm && drm->registered && priv->kms) + drm_atomic_helper_shutdown(drm); +} diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 086a3f1ff9..44aa435d68 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -195,4 +195,7 @@ static inline void msm_kms_destroy(struct msm_kms *kms) drm_for_each_crtc_reverse(crtc, dev) \ for_each_if (drm_crtc_mask(crtc) & (crtc_mask)) +int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv); +void msm_drm_kms_uninit(struct device *dev); + #endif /* __MSM_KMS_H__ */ diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index 348c66b146..29bb38f0bb 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -497,15 +497,13 @@ static int mdss_probe(struct platform_device *pdev) return 0; } -static int mdss_remove(struct platform_device *pdev) +static void mdss_remove(struct platform_device *pdev) { struct msm_mdss *mdss = platform_get_drvdata(pdev); of_platform_depopulate(&pdev->dev); msm_mdss_destroy(mdss); - - return 0; } static const struct msm_mdss_data msm8998_data = { @@ -547,7 +545,7 @@ static const struct msm_mdss_data sc8280xp_data = { .ubwc_dec_version = UBWC_4_0, .ubwc_swizzle = 6, .ubwc_static = 1, - .highest_bank_bit = 2, + .highest_bank_bit = 3, .macrotile_mode = 1, }; @@ -629,7 +627,7 @@ MODULE_DEVICE_TABLE(of, mdss_dt_match); static struct platform_driver mdss_platform_driver = { .probe = mdss_probe, - .remove = mdss_remove, + .remove_new = mdss_remove, .driver = { .name = "msm-mdss", .of_match_table = mdss_dt_match, diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index 40c0bc35a4..a7e152f659 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -21,8 +21,6 @@ static struct dma_fence *msm_job_run(struct drm_sched_job *job) msm_fence_init(submit->hw_fence, fctx); - submit->seqno = submit->hw_fence->seqno; - mutex_lock(&priv->lru.lock); for (i = 0; i < submit->nr_bos; i++) { @@ -34,8 +32,13 @@ static struct dma_fence *msm_job_run(struct drm_sched_job *job) mutex_unlock(&priv->lru.lock); + /* TODO move submit path over to using a per-ring lock.. */ + mutex_lock(&gpu->lock); + msm_gpu_submit(gpu, submit); + mutex_unlock(&gpu->lock); + return dma_fence_get(submit->hw_fence); } @@ -95,8 +98,9 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, sched_timeout = MAX_SCHEDULE_TIMEOUT; ret = drm_sched_init(&ring->sched, &msm_sched_ops, - num_hw_submissions, 0, sched_timeout, - NULL, NULL, to_msm_bo(ring->bo)->name, gpu->dev->dev); + DRM_SCHED_PRIORITY_COUNT, + num_hw_submissions, 0, sched_timeout, + NULL, NULL, to_msm_bo(ring->bo)->name, gpu->dev->dev); if (ret) { goto fail; } diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.h b/drivers/gpu/drm/msm/msm_ringbuffer.h index 698b333abc..0d6beb8cd3 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.h +++ b/drivers/gpu/drm/msm/msm_ringbuffer.h @@ -30,6 +30,8 @@ struct msm_gpu_submit_stats { struct msm_rbmemptrs { volatile uint32_t rptr; volatile uint32_t fence; + /* Introduced on A7xx */ + volatile uint32_t bv_fence; volatile struct msm_gpu_submit_stats stats[MSM_GPU_SUBMIT_STATS_COUNT]; volatile u64 ttbr0; |