diff options
Diffstat (limited to 'drivers/gpu/drm/msm')
211 files changed, 22721 insertions, 12626 deletions
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 7ec833b6d829..250246f81ea9 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -15,21 +15,13 @@ config DRM_MSM select IOMMU_IO_PGTABLE select QCOM_MDT_LOADER if ARCH_QCOM select REGULATOR - select DRM_CLIENT_SELECTION - select DRM_DISPLAY_DP_AUX_BUS - select DRM_DISPLAY_DP_HELPER - select DRM_DISPLAY_HELPER - select DRM_BRIDGE_CONNECTOR select DRM_EXEC - select DRM_KMS_HELPER - select DRM_PANEL - select DRM_BRIDGE - select DRM_PANEL_BRIDGE + select DRM_GPUVM select DRM_SCHED - select FB_SYSMEM_HELPERS if DRM_FBDEV_EMULATION select SHMEM select TMPFS select QCOM_SCM + select QCOM_UBWC_CONFIG select WANT_DEV_COREDUMP select SND_SOC_HDMI_CODEC if SND_SOC select SYNC_FILE @@ -66,6 +58,22 @@ config DRM_MSM_VALIDATE_XML Validate XML files with register definitions against rules-fd schema. This option is mostly targeting DRM MSM developers. If unsure, say N. +config DRM_MSM_KMS + def_bool n + depends on DRM_MSM + select DRM_BRIDGE + select DRM_BRIDGE_CONNECTOR + select DRM_CLIENT_SELECTION + select DRM_DISPLAY_HELPER + select DRM_KMS_HELPER + select DRM_PANEL + select DRM_PANEL_BRIDGE + +config DRM_MSM_KMS_FBDEV + def_bool DRM_FBDEV_EMULATION + depends on DRM_MSM_KMS + select FB_SYSMEM_HELPERS + config DRM_MSM_MDSS bool depends on DRM_MSM @@ -74,6 +82,7 @@ config DRM_MSM_MDSS config DRM_MSM_MDP4 bool "Enable MDP4 support in MSM DRM driver" depends on DRM_MSM + select DRM_MSM_KMS default y help Compile in support for the Mobile Display Processor v4 (MDP4) in @@ -84,6 +93,7 @@ config DRM_MSM_MDP5 bool "Enable MDP5 support in MSM DRM driver" depends on DRM_MSM select DRM_MSM_MDSS + select DRM_MSM_KMS default y help Compile in support for the Mobile Display Processor v5 (MDP5) in @@ -94,6 +104,7 @@ config DRM_MSM_DPU bool "Enable DPU support in MSM DRM driver" depends on DRM_MSM select DRM_MSM_MDSS + select DRM_MSM_KMS select DRM_DISPLAY_DSC_HELPER default y help @@ -104,7 +115,11 @@ config DRM_MSM_DPU config DRM_MSM_DP bool "Enable DisplayPort support in MSM DRM driver" depends on DRM_MSM + depends on DRM_MSM_KMS + select DRM_DISPLAY_HDMI_AUDIO_HELPER select RATIONAL + select DRM_DISPLAY_DP_AUX_BUS + select DRM_DISPLAY_DP_HELPER default y help Compile in support for DP driver in MSM DRM driver. DP external @@ -114,6 +129,7 @@ config DRM_MSM_DP config DRM_MSM_DSI bool "Enable DSI support in MSM DRM driver" depends on DRM_MSM + depends on DRM_MSM_KMS select DRM_PANEL select DRM_MIPI_DSI select DRM_DISPLAY_DSC_HELPER @@ -169,7 +185,10 @@ config DRM_MSM_DSI_7NM_PHY config DRM_MSM_HDMI bool "Enable HDMI support in MSM DRM driver" depends on DRM_MSM + depends on DRM_MSM_KMS default y + select DRM_DISPLAY_HDMI_HELPER + select DRM_DISPLAY_HDMI_STATE_HELPER help Compile in support for the HDMI output MSM DRM driver. It can be a primary or a secondary display on device. Note that this is used diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index f274d9430cc3..8aa7d07303fb 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -24,6 +24,7 @@ adreno-y := \ adreno/a6xx_gmu.o \ adreno/a6xx_hfi.o \ adreno/a6xx_preempt.o \ + adreno/a8xx_gpu.o \ adreno-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ @@ -48,7 +49,6 @@ msm-display-$(CONFIG_DRM_MSM_MDP4) += \ disp/mdp4/mdp4_dsi_encoder.o \ disp/mdp4/mdp4_dtv_encoder.o \ disp/mdp4/mdp4_lcdc_encoder.o \ - disp/mdp4/mdp4_lvds_connector.o \ disp/mdp4/mdp4_lvds_pll.o \ disp/mdp4/mdp4_irq.o \ disp/mdp4/mdp4_kms.o \ @@ -78,6 +78,7 @@ msm-display-$(CONFIG_DRM_MSM_DPU) += \ disp/dpu1/dpu_hw_catalog.o \ disp/dpu1/dpu_hw_cdm.o \ disp/dpu1/dpu_hw_ctl.o \ + disp/dpu1/dpu_hw_cwb.o \ disp/dpu1/dpu_hw_dsc.o \ disp/dpu1/dpu_hw_dsc_1_2.o \ disp/dpu1/dpu_hw_interrupts.o \ @@ -100,18 +101,15 @@ msm-display-$(CONFIG_DRM_MSM_DPU) += \ msm-display-$(CONFIG_DRM_MSM_MDSS) += \ msm_mdss.o \ -msm-display-y += \ +msm-display-$(CONFIG_DRM_MSM_KMS) += \ disp/mdp_format.o \ disp/mdp_kms.o \ disp/msm_disp_snapshot.o \ disp/msm_disp_snapshot_util.o \ msm-y += \ - msm_atomic.o \ - msm_atomic_tracepoints.o \ msm_debugfs.o \ msm_drv.o \ - msm_fb.o \ msm_fence.o \ msm_gem.o \ msm_gem_prime.o \ @@ -122,21 +120,24 @@ 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 \ msm_submitqueue.o \ + msm_syncobj.o \ msm_gpu_tracepoints.o \ -msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o +msm-$(CONFIG_DRM_MSM_KMS) += \ + msm_atomic.o \ + msm_atomic_tracepoints.o \ + msm_fb.o \ + msm_kms.o \ -msm-display-$(CONFIG_DEBUG_FS) += \ - dp/dp_debug.o +msm-$(CONFIG_DRM_MSM_KMS_FBDEV) += msm_fbdev.o msm-display-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ - dp/dp_catalog.o \ dp/dp_ctrl.o \ + dp/dp_debug.o \ dp/dp_display.o \ dp/dp_drm.o \ dp/dp_link.o \ @@ -159,7 +160,8 @@ msm-display-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/phy/dsi_phy_14nm.o msm-display-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/phy/dsi_phy_10nm.o msm-display-$(CONFIG_DRM_MSM_DSI_7NM_PHY) += dsi/phy/dsi_phy_7nm.o -msm-y += $(adreno-y) $(msm-display-y) +msm-y += $(adreno-y) +msm-$(CONFIG_DRM_MSM_KMS) += $(msm-display-y) obj-$(CONFIG_DRM_MSM) += msm.o @@ -195,6 +197,12 @@ ADRENO_HEADERS = \ generated/a4xx.xml.h \ generated/a5xx.xml.h \ generated/a6xx.xml.h \ + generated/a6xx_descriptors.xml.h \ + generated/a6xx_enums.xml.h \ + generated/a6xx_perfcntrs.xml.h \ + generated/a7xx_enums.xml.h \ + generated/a7xx_perfcntrs.xml.h \ + generated/a8xx_enums.xml.h \ generated/a6xx_gmu.xml.h \ generated/adreno_common.xml.h \ generated/adreno_pm4.xml.h \ diff --git a/drivers/gpu/drm/msm/adreno/a2xx_catalog.c b/drivers/gpu/drm/msm/adreno/a2xx_catalog.c index 9ddb7b31fd98..e9dbf3ddf89e 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a2xx_catalog.c @@ -7,6 +7,7 @@ */ #include "adreno_gpu.h" +#include "a2xx_gpu.h" static const struct adreno_info a2xx_gpus[] = { { @@ -19,7 +20,7 @@ static const struct adreno_info a2xx_gpus[] = { }, .gmem = SZ_256K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a2xx_gpu_init, + .funcs = &a2xx_gpu_funcs, }, { /* a200 on i.mx51 has only 128kib gmem */ .chip_ids = ADRENO_CHIP_IDS(0x02000001), .family = ADRENO_2XX_GEN1, @@ -30,7 +31,7 @@ static const struct adreno_info a2xx_gpus[] = { }, .gmem = SZ_128K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a2xx_gpu_init, + .funcs = &a2xx_gpu_funcs, }, { .chip_ids = ADRENO_CHIP_IDS(0x02020000), .family = ADRENO_2XX_GEN2, @@ -41,12 +42,7 @@ static const struct adreno_info a2xx_gpus[] = { }, .gmem = SZ_512K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a2xx_gpu_init, + .funcs = &a2xx_gpu_funcs, } }; DECLARE_ADRENO_GPULIST(a2xx); - -MODULE_FIRMWARE("qcom/leia_pfp_470.fw"); -MODULE_FIRMWARE("qcom/leia_pm4_470.fw"); -MODULE_FIRMWARE("qcom/yamato_pfp.fw"); -MODULE_FIRMWARE("qcom/yamato_pm4.fw"); diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c index 379a3d346c30..1b1ee14b65cf 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c @@ -113,7 +113,7 @@ static int a2xx_hw_init(struct msm_gpu *gpu) uint32_t *ptr, len; int i, ret; - a2xx_gpummu_params(gpu->aspace->mmu, &pt_base, &tran_error); + a2xx_gpummu_params(to_msm_vm(gpu->vm)->mmu, &pt_base, &tran_error); DBG("%s", gpu->name); @@ -234,7 +234,7 @@ static int a2xx_hw_init(struct msm_gpu *gpu) * word (0x20xxxx for A200, 0x220xxx for A220, 0x225xxx for A225). * Older firmware files, which lack protection support, have 0 instead. */ - if (ptr[1] == 0) { + if (ptr[1] == 0 && !a2xx_gpu->protection_disabled) { dev_warn(gpu->dev->dev, "Legacy firmware detected, disabling protection support\n"); a2xx_gpu->protection_disabled = true; @@ -466,19 +466,18 @@ static struct msm_gpu_state *a2xx_gpu_state_get(struct msm_gpu *gpu) return state; } -static struct msm_gem_address_space * -a2xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev) +static struct drm_gpuvm * +a2xx_create_vm(struct msm_gpu *gpu, struct platform_device *pdev) { struct msm_mmu *mmu = a2xx_gpummu_new(&pdev->dev, gpu); - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; - aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M, - 0xfff * SZ_64K); + vm = msm_gem_vm_create(gpu->dev, mmu, "gpu", SZ_16M, 0xfff * SZ_64K, true); - if (IS_ERR(aspace) && !IS_ERR(mmu)) + if (IS_ERR(vm) && !IS_ERR(mmu)) mmu->funcs->destroy(mmu); - return aspace; + return vm; } static u32 a2xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) @@ -487,39 +486,18 @@ static u32 a2xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) return ring->memptrs->rptr; } -static const struct adreno_gpu_funcs funcs = { - .base = { - .get_param = adreno_get_param, - .set_param = adreno_set_param, - .hw_init = a2xx_hw_init, - .pm_suspend = msm_gpu_pm_suspend, - .pm_resume = msm_gpu_pm_resume, - .recover = a2xx_recover, - .submit = a2xx_submit, - .active_ring = adreno_active_ring, - .irq = a2xx_irq, - .destroy = a2xx_destroy, -#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) - .show = adreno_show, -#endif - .gpu_state_get = a2xx_gpu_state_get, - .gpu_state_put = adreno_gpu_state_put, - .create_address_space = a2xx_create_address_space, - .get_rptr = a2xx_get_rptr, - }, -}; - static const struct msm_gpu_perfcntr perfcntrs[] = { /* TODO */ }; -struct msm_gpu *a2xx_gpu_init(struct drm_device *dev) +static struct msm_gpu *a2xx_gpu_init(struct drm_device *dev) { struct a2xx_gpu *a2xx_gpu = NULL; struct adreno_gpu *adreno_gpu; struct msm_gpu *gpu; struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = priv->gpu_pdev; + struct adreno_platform_config *config = pdev->dev.platform_data; int ret; if (!pdev) { @@ -540,7 +518,7 @@ struct msm_gpu *a2xx_gpu_init(struct drm_device *dev) gpu->perfcntrs = perfcntrs; gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs); - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, config->info->funcs, 1); if (ret) goto fail; @@ -551,14 +529,6 @@ struct msm_gpu *a2xx_gpu_init(struct drm_device *dev) else adreno_gpu->registers = a220_registers; - if (!gpu->aspace) { - dev_err(dev->dev, "No memory protection without MMU\n"); - if (!allow_vram_carveout) { - ret = -ENXIO; - goto fail; - } - } - return gpu; fail: @@ -567,3 +537,26 @@ fail: return ERR_PTR(ret); } + +const struct adreno_gpu_funcs a2xx_gpu_funcs = { + .base = { + .get_param = adreno_get_param, + .set_param = adreno_set_param, + .hw_init = a2xx_hw_init, + .pm_suspend = msm_gpu_pm_suspend, + .pm_resume = msm_gpu_pm_resume, + .recover = a2xx_recover, + .submit = a2xx_submit, + .active_ring = adreno_active_ring, + .irq = a2xx_irq, + .destroy = a2xx_destroy, +#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) + .show = adreno_show, +#endif + .gpu_state_get = a2xx_gpu_state_get, + .gpu_state_put = adreno_gpu_state_put, + .create_vm = a2xx_create_vm, + .get_rptr = a2xx_get_rptr, + }, + .init = a2xx_gpu_init, +}; diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.h b/drivers/gpu/drm/msm/adreno/a2xx_gpu.h index 53702f19990f..162ef98951f5 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.h @@ -19,6 +19,8 @@ struct a2xx_gpu { }; #define to_a2xx_gpu(x) container_of(x, struct a2xx_gpu, base) +extern const struct adreno_gpu_funcs a2xx_gpu_funcs; + struct msm_mmu *a2xx_gpummu_new(struct device *dev, struct msm_gpu *gpu); void a2xx_gpummu_params(struct msm_mmu *mmu, dma_addr_t *pt_base, dma_addr_t *tran_error); diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c b/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c index 39641551eeb6..0407c9bc8c1b 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c @@ -29,13 +29,16 @@ static void a2xx_gpummu_detach(struct msm_mmu *mmu) } static int a2xx_gpummu_map(struct msm_mmu *mmu, uint64_t iova, - struct sg_table *sgt, size_t len, int prot) + struct sg_table *sgt, size_t off, size_t len, + int prot) { struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu); unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE; struct sg_dma_page_iter dma_iter; unsigned prot_bits = 0; + WARN_ON(off != 0); + if (prot & IOMMU_WRITE) prot_bits |= 1; if (prot & IOMMU_READ) @@ -71,10 +74,6 @@ static int a2xx_gpummu_unmap(struct msm_mmu *mmu, uint64_t iova, size_t len) return 0; } -static void a2xx_gpummu_resume_translation(struct msm_mmu *mmu) -{ -} - static void a2xx_gpummu_destroy(struct msm_mmu *mmu) { struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu); @@ -90,7 +89,6 @@ static const struct msm_mmu_funcs funcs = { .map = a2xx_gpummu_map, .unmap = a2xx_gpummu_unmap, .destroy = a2xx_gpummu_destroy, - .resume_translation = a2xx_gpummu_resume_translation, }; struct msm_mmu *a2xx_gpummu_new(struct device *dev, struct msm_gpu *gpu) diff --git a/drivers/gpu/drm/msm/adreno/a3xx_catalog.c b/drivers/gpu/drm/msm/adreno/a3xx_catalog.c index 2eb6c3e93748..6ae8716fc08a 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_catalog.c @@ -7,6 +7,7 @@ */ #include "adreno_gpu.h" +#include "a3xx_gpu.h" static const struct adreno_info a3xx_gpus[] = { { @@ -18,7 +19,7 @@ static const struct adreno_info a3xx_gpus[] = { }, .gmem = SZ_128K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a3xx_gpu_init, + .funcs = &a3xx_gpu_funcs, }, { .chip_ids = ADRENO_CHIP_IDS(0x03000520), .family = ADRENO_3XX, @@ -29,7 +30,7 @@ static const struct adreno_info a3xx_gpus[] = { }, .gmem = SZ_256K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a3xx_gpu_init, + .funcs = &a3xx_gpu_funcs, }, { .chip_ids = ADRENO_CHIP_IDS(0x03000600), .family = ADRENO_3XX, @@ -40,7 +41,7 @@ static const struct adreno_info a3xx_gpus[] = { }, .gmem = SZ_128K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a3xx_gpu_init, + .funcs = &a3xx_gpu_funcs, }, { .chip_ids = ADRENO_CHIP_IDS(0x03000620), .family = ADRENO_3XX, @@ -51,7 +52,7 @@ static const struct adreno_info a3xx_gpus[] = { }, .gmem = SZ_128K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a3xx_gpu_init, + .funcs = &a3xx_gpu_funcs, }, { .chip_ids = ADRENO_CHIP_IDS( 0x03020000, @@ -66,7 +67,7 @@ static const struct adreno_info a3xx_gpus[] = { }, .gmem = SZ_512K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a3xx_gpu_init, + .funcs = &a3xx_gpu_funcs, }, { .chip_ids = ADRENO_CHIP_IDS( 0x03030000, @@ -81,12 +82,7 @@ static const struct adreno_info a3xx_gpus[] = { }, .gmem = SZ_1M, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a3xx_gpu_init, + .funcs = &a3xx_gpu_funcs, } }; DECLARE_ADRENO_GPULIST(a3xx); - -MODULE_FIRMWARE("qcom/a300_pm4.fw"); -MODULE_FIRMWARE("qcom/a300_pfp.fw"); -MODULE_FIRMWARE("qcom/a330_pm4.fw"); -MODULE_FIRMWARE("qcom/a330_pfp.fw"); diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index b6df115bb567..f22d33e99e81 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -508,29 +508,6 @@ static u32 a3xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) return ring->memptrs->rptr; } -static const struct adreno_gpu_funcs funcs = { - .base = { - .get_param = adreno_get_param, - .set_param = adreno_set_param, - .hw_init = a3xx_hw_init, - .pm_suspend = msm_gpu_pm_suspend, - .pm_resume = msm_gpu_pm_resume, - .recover = a3xx_recover, - .submit = a3xx_submit, - .active_ring = adreno_active_ring, - .irq = a3xx_irq, - .destroy = a3xx_destroy, -#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) - .show = adreno_show, -#endif - .gpu_busy = a3xx_gpu_busy, - .gpu_state_get = a3xx_gpu_state_get, - .gpu_state_put = adreno_gpu_state_put, - .create_address_space = adreno_create_address_space, - .get_rptr = a3xx_get_rptr, - }, -}; - static const struct msm_gpu_perfcntr perfcntrs[] = { { REG_A3XX_SP_PERFCOUNTER6_SELECT, REG_A3XX_RBBM_PERFCTR_SP_6_LO, SP_ALU_ACTIVE_CYCLES, "ALUACTIVE" }, @@ -538,13 +515,14 @@ static const struct msm_gpu_perfcntr perfcntrs[] = { SP_FS_FULL_ALU_INSTRUCTIONS, "ALUFULL" }, }; -struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) +static struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) { struct a3xx_gpu *a3xx_gpu = NULL; struct adreno_gpu *adreno_gpu; struct msm_gpu *gpu; struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = priv->gpu_pdev; + struct adreno_platform_config *config = pdev->dev.platform_data; struct icc_path *ocmem_icc_path; struct icc_path *icc_path; int ret; @@ -569,7 +547,7 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) adreno_gpu->registers = a3xx_registers; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, config->info->funcs, 1); if (ret) goto fail; @@ -581,21 +559,6 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) goto fail; } - if (!gpu->aspace) { - /* TODO we think it is possible to configure the GPU to - * restrict access to VRAM carveout. But the required - * registers are unknown. For now just bail out and - * limp along with just modesetting. If it turns out - * to not be possible to restrict access, then we must - * implement a cmdstream validator. - */ - DRM_DEV_ERROR(dev->dev, "No memory protection without IOMMU\n"); - if (!allow_vram_carveout) { - ret = -ENXIO; - goto fail; - } - } - icc_path = devm_of_icc_get(&pdev->dev, "gfx-mem"); if (IS_ERR(icc_path)) { ret = PTR_ERR(icc_path); @@ -628,3 +591,27 @@ fail: return ERR_PTR(ret); } + +const struct adreno_gpu_funcs a3xx_gpu_funcs = { + .base = { + .get_param = adreno_get_param, + .set_param = adreno_set_param, + .hw_init = a3xx_hw_init, + .pm_suspend = msm_gpu_pm_suspend, + .pm_resume = msm_gpu_pm_resume, + .recover = a3xx_recover, + .submit = a3xx_submit, + .active_ring = adreno_active_ring, + .irq = a3xx_irq, + .destroy = a3xx_destroy, +#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) + .show = adreno_show, +#endif + .gpu_busy = a3xx_gpu_busy, + .gpu_state_get = a3xx_gpu_state_get, + .gpu_state_put = adreno_gpu_state_put, + .create_vm = adreno_create_vm, + .get_rptr = a3xx_get_rptr, + }, + .init = a3xx_gpu_init, +}; diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.h b/drivers/gpu/drm/msm/adreno/a3xx_gpu.h index c555fb13e0d7..3d4ec9dbd918 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.h @@ -23,4 +23,6 @@ struct a3xx_gpu { }; #define to_a3xx_gpu(x) container_of(x, struct a3xx_gpu, base) +extern const struct adreno_gpu_funcs a3xx_gpu_funcs; + #endif /* __A3XX_GPU_H__ */ diff --git a/drivers/gpu/drm/msm/adreno/a4xx_catalog.c b/drivers/gpu/drm/msm/adreno/a4xx_catalog.c index 93519f807f87..9192586f7ef0 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_catalog.c @@ -7,6 +7,7 @@ */ #include "adreno_gpu.h" +#include "a4xx_gpu.h" static const struct adreno_info a4xx_gpus[] = { { @@ -19,7 +20,7 @@ static const struct adreno_info a4xx_gpus[] = { }, .gmem = SZ_256K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a4xx_gpu_init, + .funcs = &a4xx_gpu_funcs, }, { .chip_ids = ADRENO_CHIP_IDS(0x04020000), .family = ADRENO_4XX, @@ -30,7 +31,7 @@ static const struct adreno_info a4xx_gpus[] = { }, .gmem = (SZ_1M + SZ_512K), .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a4xx_gpu_init, + .funcs = &a4xx_gpu_funcs, }, { .chip_ids = ADRENO_CHIP_IDS(0x04030002), .family = ADRENO_4XX, @@ -41,10 +42,7 @@ static const struct adreno_info a4xx_gpus[] = { }, .gmem = (SZ_1M + SZ_512K), .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a4xx_gpu_init, + .funcs = &a4xx_gpu_funcs, } }; DECLARE_ADRENO_GPULIST(a4xx); - -MODULE_FIRMWARE("qcom/a420_pm4.fw"); -MODULE_FIRMWARE("qcom/a420_pfp.fw"); diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 50c490b492f0..db06c06067ae 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -251,8 +251,8 @@ static int a4xx_hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_A4XX_UCHE_CACHE_WAYS_VFD, 0x07); /* Disable L2 bypass to avoid UCHE out of bounds errors */ - gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_LO, 0xffff0000); - gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_HI, 0xffff0000); + gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_LO, lower_32_bits(adreno_gpu->uche_trap_base)); + gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_HI, upper_32_bits(adreno_gpu->uche_trap_base)); gpu_write(gpu, REG_A4XX_CP_DEBUG, (1 << 25) | (adreno_is_a420(adreno_gpu) ? (1 << 29) : 0)); @@ -627,37 +627,14 @@ static u32 a4xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) return ring->memptrs->rptr; } -static const struct adreno_gpu_funcs funcs = { - .base = { - .get_param = adreno_get_param, - .set_param = adreno_set_param, - .hw_init = a4xx_hw_init, - .pm_suspend = a4xx_pm_suspend, - .pm_resume = a4xx_pm_resume, - .recover = a4xx_recover, - .submit = a4xx_submit, - .active_ring = adreno_active_ring, - .irq = a4xx_irq, - .destroy = a4xx_destroy, -#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) - .show = adreno_show, -#endif - .gpu_busy = a4xx_gpu_busy, - .gpu_state_get = a4xx_gpu_state_get, - .gpu_state_put = adreno_gpu_state_put, - .create_address_space = adreno_create_address_space, - .get_rptr = a4xx_get_rptr, - }, - .get_timestamp = a4xx_get_timestamp, -}; - -struct msm_gpu *a4xx_gpu_init(struct drm_device *dev) +static struct msm_gpu *a4xx_gpu_init(struct drm_device *dev) { struct a4xx_gpu *a4xx_gpu = NULL; struct adreno_gpu *adreno_gpu; struct msm_gpu *gpu; struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = priv->gpu_pdev; + struct adreno_platform_config *config = pdev->dev.platform_data; struct icc_path *ocmem_icc_path; struct icc_path *icc_path; int ret; @@ -680,7 +657,7 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev) gpu->perfcntrs = NULL; gpu->num_perfcntrs = 0; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, config->info->funcs, 1); if (ret) goto fail; @@ -693,20 +670,7 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev) if (ret) goto fail; - if (!gpu->aspace) { - /* TODO we think it is possible to configure the GPU to - * restrict access to VRAM carveout. But the required - * registers are unknown. For now just bail out and - * limp along with just modesetting. If it turns out - * to not be possible to restrict access, then we must - * implement a cmdstream validator. - */ - DRM_DEV_ERROR(dev->dev, "No memory protection without IOMMU\n"); - if (!allow_vram_carveout) { - ret = -ENXIO; - goto fail; - } - } + adreno_gpu->uche_trap_base = 0xffff0000ffff0000ull; icc_path = devm_of_icc_get(&pdev->dev, "gfx-mem"); if (IS_ERR(icc_path)) { @@ -739,3 +703,28 @@ fail: return ERR_PTR(ret); } + +const struct adreno_gpu_funcs a4xx_gpu_funcs = { + .base = { + .get_param = adreno_get_param, + .set_param = adreno_set_param, + .hw_init = a4xx_hw_init, + .pm_suspend = a4xx_pm_suspend, + .pm_resume = a4xx_pm_resume, + .recover = a4xx_recover, + .submit = a4xx_submit, + .active_ring = adreno_active_ring, + .irq = a4xx_irq, + .destroy = a4xx_destroy, +#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) + .show = adreno_show, +#endif + .gpu_busy = a4xx_gpu_busy, + .gpu_state_get = a4xx_gpu_state_get, + .gpu_state_put = adreno_gpu_state_put, + .create_vm = adreno_create_vm, + .get_rptr = a4xx_get_rptr, + }, + .init = a4xx_gpu_init, + .get_timestamp = a4xx_get_timestamp, +}; diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.h b/drivers/gpu/drm/msm/adreno/a4xx_gpu.h index a01448cba2ea..71b164439f62 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.h @@ -20,4 +20,6 @@ struct a4xx_gpu { }; #define to_a4xx_gpu(x) container_of(x, struct a4xx_gpu, base) +extern const struct adreno_gpu_funcs a4xx_gpu_funcs; + #endif /* __A4XX_GPU_H__ */ diff --git a/drivers/gpu/drm/msm/adreno/a5xx_catalog.c b/drivers/gpu/drm/msm/adreno/a5xx_catalog.c index 633f31539162..babd320f3b73 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_catalog.c @@ -7,6 +7,7 @@ */ #include "adreno_gpu.h" +#include "a5xx_gpu.h" static const struct adreno_info a5xx_gpus[] = { { @@ -21,7 +22,7 @@ static const struct adreno_info a5xx_gpus[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI | ADRENO_QUIRK_LMLOADKILL_DISABLE, - .init = a5xx_gpu_init, + .funcs = &a5xx_gpu_funcs, }, { .chip_ids = ADRENO_CHIP_IDS(0x05000600), .family = ADRENO_5XX, @@ -38,7 +39,7 @@ static const struct adreno_info a5xx_gpus[] = { .inactive_period = 250, .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI | ADRENO_QUIRK_LMLOADKILL_DISABLE, - .init = a5xx_gpu_init, + .funcs = &a5xx_gpu_funcs, .zapfw = "a506_zap.mdt", }, { .chip_ids = ADRENO_CHIP_IDS(0x05000800), @@ -55,7 +56,7 @@ static const struct adreno_info a5xx_gpus[] = { */ .inactive_period = 250, .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE, - .init = a5xx_gpu_init, + .funcs = &a5xx_gpu_funcs, .zapfw = "a508_zap.mdt", }, { .chip_ids = ADRENO_CHIP_IDS(0x05000900), @@ -72,7 +73,7 @@ static const struct adreno_info a5xx_gpus[] = { */ .inactive_period = 250, .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE, - .init = a5xx_gpu_init, + .funcs = &a5xx_gpu_funcs, /* Adreno 509 uses the same ZAP as 512 */ .zapfw = "a512_zap.mdt", }, { @@ -89,7 +90,7 @@ static const struct adreno_info a5xx_gpus[] = { * the GDSC which appears to make it grumpy */ .inactive_period = 250, - .init = a5xx_gpu_init, + .funcs = &a5xx_gpu_funcs, }, { .chip_ids = ADRENO_CHIP_IDS(0x05010200), .family = ADRENO_5XX, @@ -105,7 +106,7 @@ static const struct adreno_info a5xx_gpus[] = { */ .inactive_period = 250, .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE, - .init = a5xx_gpu_init, + .funcs = &a5xx_gpu_funcs, .zapfw = "a512_zap.mdt", }, { .chip_ids = ADRENO_CHIP_IDS( @@ -127,7 +128,7 @@ static const struct adreno_info a5xx_gpus[] = { .inactive_period = 250, .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI | ADRENO_QUIRK_FAULT_DETECT_MASK, - .init = a5xx_gpu_init, + .funcs = &a5xx_gpu_funcs, .zapfw = "a530_zap.mdt", }, { .chip_ids = ADRENO_CHIP_IDS(0x05040001), @@ -145,17 +146,8 @@ static const struct adreno_info a5xx_gpus[] = { */ .inactive_period = 250, .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE, - .init = a5xx_gpu_init, + .funcs = &a5xx_gpu_funcs, .zapfw = "a540_zap.mdt", } }; DECLARE_ADRENO_GPULIST(a5xx); - -MODULE_FIRMWARE("qcom/a530_pm4.fw"); -MODULE_FIRMWARE("qcom/a530_pfp.fw"); -MODULE_FIRMWARE("qcom/a530v3_gpmu.fw2"); -MODULE_FIRMWARE("qcom/a530_zap.mdt"); -MODULE_FIRMWARE("qcom/a530_zap.b00"); -MODULE_FIRMWARE("qcom/a530_zap.b01"); -MODULE_FIRMWARE("qcom/a530_zap.b02"); -MODULE_FIRMWARE("qcom/a540_gpmu.fw2"); diff --git a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c index 169b8fe688f8..625a4e787d8f 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c @@ -116,13 +116,13 @@ reset_set(void *data, u64 val) adreno_gpu->fw[ADRENO_FW_PFP] = NULL; if (a5xx_gpu->pm4_bo) { - msm_gem_unpin_iova(a5xx_gpu->pm4_bo, gpu->aspace); + msm_gem_unpin_iova(a5xx_gpu->pm4_bo, gpu->vm); drm_gem_object_put(a5xx_gpu->pm4_bo); a5xx_gpu->pm4_bo = NULL; } if (a5xx_gpu->pfp_bo) { - msm_gem_unpin_iova(a5xx_gpu->pfp_bo, gpu->aspace); + msm_gem_unpin_iova(a5xx_gpu->pfp_bo, gpu->vm); drm_gem_object_put(a5xx_gpu->pfp_bo); a5xx_gpu->pfp_bo = NULL; } diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index ee89db72e36e..56eaff2ee4e4 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -131,6 +131,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) struct msm_ringbuffer *ring = submit->ring; unsigned int i, ibs = 0; + adreno_check_and_reenable_stall(adreno_gpu); + if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) { ring->cur_ctx_seqno = 0; a5xx_submit_in_rb(gpu, submit); @@ -620,7 +622,7 @@ static int a5xx_ucode_load(struct msm_gpu *gpu) a5xx_gpu->shadow = msm_gem_kernel_new(gpu->dev, sizeof(u32) * gpu->nr_rings, MSM_BO_WC | MSM_BO_MAP_PRIV, - gpu->aspace, &a5xx_gpu->shadow_bo, + gpu->vm, &a5xx_gpu->shadow_bo, &a5xx_gpu->shadow_iova); if (IS_ERR(a5xx_gpu->shadow)) @@ -750,10 +752,10 @@ static int a5xx_hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02); /* Disable L2 bypass in the UCHE */ - gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, 0xFFFF0000); - gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, 0x0001FFFF); - gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, 0xFFFF0000); - gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, 0x0001FFFF); + gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, lower_32_bits(adreno_gpu->uche_trap_base)); + gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, upper_32_bits(adreno_gpu->uche_trap_base)); + gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, lower_32_bits(adreno_gpu->uche_trap_base)); + gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, upper_32_bits(adreno_gpu->uche_trap_base)); /* Set the GMEM VA range (0 to gpu->gmem) */ gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000); @@ -833,8 +835,8 @@ static int a5xx_hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL2, 0x0000003F); - BUG_ON(adreno_gpu->ubwc_config.highest_bank_bit < 13); - hbb = adreno_gpu->ubwc_config.highest_bank_bit - 13; + BUG_ON(adreno_gpu->ubwc_config->highest_bank_bit < 13); + hbb = adreno_gpu->ubwc_config->highest_bank_bit - 13; gpu_write(gpu, REG_A5XX_TPL1_MODE_CNTL, hbb << 7); gpu_write(gpu, REG_A5XX_RB_MODE_CNTL, hbb << 1); @@ -1040,22 +1042,22 @@ static void a5xx_destroy(struct msm_gpu *gpu) a5xx_preempt_fini(gpu); if (a5xx_gpu->pm4_bo) { - msm_gem_unpin_iova(a5xx_gpu->pm4_bo, gpu->aspace); + msm_gem_unpin_iova(a5xx_gpu->pm4_bo, gpu->vm); drm_gem_object_put(a5xx_gpu->pm4_bo); } if (a5xx_gpu->pfp_bo) { - msm_gem_unpin_iova(a5xx_gpu->pfp_bo, gpu->aspace); + msm_gem_unpin_iova(a5xx_gpu->pfp_bo, gpu->vm); drm_gem_object_put(a5xx_gpu->pfp_bo); } if (a5xx_gpu->gpmu_bo) { - msm_gem_unpin_iova(a5xx_gpu->gpmu_bo, gpu->aspace); + msm_gem_unpin_iova(a5xx_gpu->gpmu_bo, gpu->vm); drm_gem_object_put(a5xx_gpu->gpmu_bo); } if (a5xx_gpu->shadow_bo) { - msm_gem_unpin_iova(a5xx_gpu->shadow_bo, gpu->aspace); + msm_gem_unpin_iova(a5xx_gpu->shadow_bo, gpu->vm); drm_gem_object_put(a5xx_gpu->shadow_bo); } @@ -1253,7 +1255,7 @@ static void a5xx_fault_detect_irq(struct msm_gpu *gpu) gpu_read(gpu, REG_A5XX_CP_IB2_BUFSZ)); /* Turn off the hangcheck timer to keep it from bothering us */ - del_timer(&gpu->hangcheck_timer); + timer_delete(&gpu->hangcheck_timer); kthread_queue_work(gpu->worker, &gpu->recover_work); } @@ -1455,7 +1457,7 @@ static int a5xx_crashdumper_init(struct msm_gpu *gpu, struct a5xx_crashdumper *dumper) { dumper->ptr = msm_gem_kernel_new(gpu->dev, - SZ_1M, MSM_BO_WC, gpu->aspace, + SZ_1M, MSM_BO_WC, gpu->vm, &dumper->bo, &dumper->iova); if (!IS_ERR(dumper->ptr)) @@ -1555,7 +1557,7 @@ static void a5xx_gpu_state_get_hlsq_regs(struct msm_gpu *gpu, if (a5xx_crashdumper_run(gpu, &dumper)) { kfree(a5xx_state->hlsqregs); - msm_gem_kernel_put(dumper.bo, gpu->aspace); + msm_gem_kernel_put(dumper.bo, gpu->vm); return; } @@ -1563,7 +1565,7 @@ static void a5xx_gpu_state_get_hlsq_regs(struct msm_gpu *gpu, memcpy(a5xx_state->hlsqregs, dumper.ptr + (256 * SZ_1K), count * sizeof(u32)); - msm_gem_kernel_put(dumper.bo, gpu->aspace); + msm_gem_kernel_put(dumper.bo, gpu->vm); } static struct msm_gpu_state *a5xx_gpu_state_get(struct msm_gpu *gpu) @@ -1689,34 +1691,6 @@ static uint32_t a5xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) return ring->memptrs->rptr = gpu_read(gpu, REG_A5XX_CP_RB_RPTR); } -static const struct adreno_gpu_funcs funcs = { - .base = { - .get_param = adreno_get_param, - .set_param = adreno_set_param, - .hw_init = a5xx_hw_init, - .ucode_load = a5xx_ucode_load, - .pm_suspend = a5xx_pm_suspend, - .pm_resume = a5xx_pm_resume, - .recover = a5xx_recover, - .submit = a5xx_submit, - .active_ring = a5xx_active_ring, - .irq = a5xx_irq, - .destroy = a5xx_destroy, -#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) - .show = a5xx_show, -#endif -#if defined(CONFIG_DEBUG_FS) - .debugfs_init = a5xx_debugfs_init, -#endif - .gpu_busy = a5xx_gpu_busy, - .gpu_state_get = a5xx_gpu_state_get, - .gpu_state_put = a5xx_gpu_state_put, - .create_address_space = adreno_create_address_space, - .get_rptr = a5xx_get_rptr, - }, - .get_timestamp = a5xx_get_timestamp, -}; - static void check_speed_bin(struct device *dev) { struct nvmem_cell *cell; @@ -1749,22 +1723,18 @@ static void check_speed_bin(struct device *dev) devm_pm_opp_set_supported_hw(dev, &val, 1); } -struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) +static struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = priv->gpu_pdev; struct adreno_platform_config *config = pdev->dev.platform_data; + const struct qcom_ubwc_cfg_data *common_cfg; struct a5xx_gpu *a5xx_gpu = NULL; struct adreno_gpu *adreno_gpu; struct msm_gpu *gpu; unsigned int nr_rings; int ret; - if (!pdev) { - DRM_DEV_ERROR(dev->dev, "No A5XX device is defined\n"); - return ERR_PTR(-ENXIO); - } - a5xx_gpu = kzalloc(sizeof(*a5xx_gpu), GFP_KERNEL); if (!a5xx_gpu) return ERR_PTR(-ENOMEM); @@ -1783,27 +1753,57 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) if (config->info->revn == 510) nr_rings = 1; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, nr_rings); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, config->info->funcs, nr_rings); if (ret) { a5xx_destroy(&(a5xx_gpu->base.base)); return ERR_PTR(ret); } - if (gpu->aspace) - msm_mmu_set_fault_handler(gpu->aspace->mmu, gpu, a5xx_fault_handler); + msm_mmu_set_fault_handler(to_msm_vm(gpu->vm)->mmu, gpu, + a5xx_fault_handler); /* Set up the preemption specific bits and pieces for each ringbuffer */ a5xx_preempt_init(gpu); - /* Set the highest bank bit */ - if (adreno_is_a540(adreno_gpu) || adreno_is_a530(adreno_gpu)) - adreno_gpu->ubwc_config.highest_bank_bit = 15; - else - adreno_gpu->ubwc_config.highest_bank_bit = 14; + /* Inherit the common config and make some necessary fixups */ + common_cfg = qcom_ubwc_config_get_data(); + if (IS_ERR(common_cfg)) + return ERR_CAST(common_cfg); + + /* Copy the data into the internal struct to drop the const qualifier (temporarily) */ + adreno_gpu->_ubwc_config = *common_cfg; + adreno_gpu->ubwc_config = &adreno_gpu->_ubwc_config; - /* a5xx only supports UBWC 1.0, these are not configurable */ - adreno_gpu->ubwc_config.macrotile_mode = 0; - adreno_gpu->ubwc_config.ubwc_swizzle = 0x7; + adreno_gpu->uche_trap_base = 0x0001ffffffff0000ull; return gpu; } + +const struct adreno_gpu_funcs a5xx_gpu_funcs = { + .base = { + .get_param = adreno_get_param, + .set_param = adreno_set_param, + .hw_init = a5xx_hw_init, + .ucode_load = a5xx_ucode_load, + .pm_suspend = a5xx_pm_suspend, + .pm_resume = a5xx_pm_resume, + .recover = a5xx_recover, + .submit = a5xx_submit, + .active_ring = a5xx_active_ring, + .irq = a5xx_irq, + .destroy = a5xx_destroy, +#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) + .show = a5xx_show, +#endif +#if defined(CONFIG_DEBUG_FS) + .debugfs_init = a5xx_debugfs_init, +#endif + .gpu_busy = a5xx_gpu_busy, + .gpu_state_get = a5xx_gpu_state_get, + .gpu_state_put = a5xx_gpu_state_put, + .create_vm = adreno_create_vm, + .get_rptr = a5xx_get_rptr, + }, + .init = a5xx_gpu_init, + .get_timestamp = a5xx_get_timestamp, +}; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h index 9c0d701fe4b8..407bb950d350 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h @@ -133,6 +133,7 @@ struct a5xx_preempt_record { */ #define A5XX_PREEMPT_COUNTER_SIZE (16 * 4) +extern const struct adreno_gpu_funcs a5xx_gpu_funcs; int a5xx_power_init(struct msm_gpu *gpu); void a5xx_gpmu_ucode_init(struct msm_gpu *gpu); diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c index 6b91e0bd1514..d6da7351cfbb 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_power.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c @@ -363,7 +363,7 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu) bosize = (cmds_size + (cmds_size / TYPE4_MAX_PAYLOAD) + 1) << 2; ptr = msm_gem_kernel_new(drm, bosize, - MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->aspace, + MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->vm, &a5xx_gpu->gpmu_bo, &a5xx_gpu->gpmu_iova); if (IS_ERR(ptr)) return; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c index 0469fea55010..e4924b5e1c48 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c @@ -79,7 +79,8 @@ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu) static void a5xx_preempt_timer(struct timer_list *t) { - struct a5xx_gpu *a5xx_gpu = from_timer(a5xx_gpu, t, preempt_timer); + struct a5xx_gpu *a5xx_gpu = timer_container_of(a5xx_gpu, t, + preempt_timer); struct msm_gpu *gpu = &a5xx_gpu->base.base; struct drm_device *dev = gpu->dev; @@ -182,7 +183,7 @@ void a5xx_preempt_irq(struct msm_gpu *gpu) return; /* Delete the preemption watchdog timer */ - del_timer(&a5xx_gpu->preempt_timer); + timer_delete(&a5xx_gpu->preempt_timer); /* * The hardware should be setting CP_CONTEXT_SWITCH_CNTL to zero before @@ -254,7 +255,7 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu, ptr = msm_gem_kernel_new(gpu->dev, A5XX_PREEMPT_RECORD_SIZE + A5XX_PREEMPT_COUNTER_SIZE, - MSM_BO_WC | MSM_BO_MAP_PRIV, gpu->aspace, &bo, &iova); + MSM_BO_WC | MSM_BO_MAP_PRIV, gpu->vm, &bo, &iova); if (IS_ERR(ptr)) return PTR_ERR(ptr); @@ -262,9 +263,9 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu, /* The buffer to store counters needs to be unprivileged */ counters = msm_gem_kernel_new(gpu->dev, A5XX_PREEMPT_COUNTER_SIZE, - MSM_BO_WC, gpu->aspace, &counters_bo, &counters_iova); + MSM_BO_WC, gpu->vm, &counters_bo, &counters_iova); if (IS_ERR(counters)) { - msm_gem_kernel_put(bo, gpu->aspace); + msm_gem_kernel_put(bo, gpu->vm); return PTR_ERR(counters); } @@ -295,8 +296,8 @@ void a5xx_preempt_fini(struct msm_gpu *gpu) int i; for (i = 0; i < gpu->nr_rings; i++) { - msm_gem_kernel_put(a5xx_gpu->preempt_bo[i], gpu->aspace); - msm_gem_kernel_put(a5xx_gpu->preempt_counters_bo[i], gpu->aspace); + msm_gem_kernel_put(a5xx_gpu->preempt_bo[i], gpu->vm); + msm_gem_kernel_put(a5xx_gpu->preempt_counters_bo[i], gpu->vm); } } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c index 0c560e84ad5a..29107b362346 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c @@ -672,6 +672,14 @@ static const u32 a690_protect_regs[] = { }; DECLARE_ADRENO_PROTECT(a690_protect, 48); +static const struct adreno_reglist a640_gbif[] = { + { REG_A6XX_GBIF_QSB_SIDE0, 0x00071620 }, + { REG_A6XX_GBIF_QSB_SIDE1, 0x00071620 }, + { REG_A6XX_GBIF_QSB_SIDE2, 0x00071620 }, + { REG_A6XX_GBIF_QSB_SIDE3, 0x00071620 }, + { }, +}; + static const struct adreno_info a6xx_gpus[] = { { .chip_ids = ADRENO_CHIP_IDS(0x06010000), @@ -681,12 +689,14 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_SQE] = "a630_sqe.fw", }, .gmem = (SZ_128K + SZ_4K), + .quirks = ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a6xx_gpu_init, + .funcs = &a6xx_gmuwrapper_funcs, .zapfw = "a610_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a612_hwcg, .protect = &a630_protect, + .gbif_cx = a640_gbif, .gmu_cgc_mode = 0x00020202, .prim_fifo_threshold = 0x00080000, }, @@ -705,6 +715,22 @@ static const struct adreno_info a6xx_gpus[] = { { 127, 4 }, ), }, { + .chip_ids = ADRENO_CHIP_IDS(0x06010200), + .family = ADRENO_6XX_GEN1, + .fw = { + [ADRENO_FW_SQE] = "a630_sqe.fw", + [ADRENO_FW_GMU] = "a612_rgmu.bin", + }, + .gmem = (SZ_128K + SZ_4K), + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .funcs = &a6xx_gmuwrapper_funcs, + .a6xx = &(const struct a6xx_info) { + .hwcg = a612_hwcg, + .protect = &a630_protect, + .gmu_cgc_mode = 0x00000022, + .prim_fifo_threshold = 0x00080000, + }, + }, { .chip_ids = ADRENO_CHIP_IDS(0x06010500), .family = ADRENO_6XX_GEN1, .revn = 615, @@ -713,8 +739,9 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a630_gmu.bin", }, .gmem = SZ_512K, + .quirks = ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a615_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a615_hwcg, @@ -743,8 +770,9 @@ static const struct adreno_info a6xx_gpus[] = { }, .gmem = SZ_512K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, - .init = a6xx_gpu_init, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, + .funcs = &a6xx_gpu_funcs, .zapfw = "a615_zap.mbn", .a6xx = &(const struct a6xx_info) { .hwcg = a615_hwcg, @@ -769,8 +797,9 @@ static const struct adreno_info a6xx_gpus[] = { }, .gmem = SZ_512K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, - .init = a6xx_gpu_init, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, + .funcs = &a6xx_gpu_funcs, .a6xx = &(const struct a6xx_info) { .protect = &a630_protect, .gmu_cgc_mode = 0x00000222, @@ -791,8 +820,9 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a619_gmu.bin", }, .gmem = SZ_512K, + .quirks = ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a615_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a615_hwcg, @@ -815,8 +845,9 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a619_gmu.bin", }, .gmem = SZ_512K, + .quirks = ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a615_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a615_hwcg, @@ -838,9 +869,10 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a619_gmu.bin", }, .gmem = SZ_512K, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a615_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a615_hwcg, @@ -866,20 +898,54 @@ static const struct adreno_info a6xx_gpus[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | ADRENO_QUIRK_HAS_HW_APRIV, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a620_zap.mbn", .a6xx = &(const struct a6xx_info) { .hwcg = a620_hwcg, .protect = &a650_protect, + .gbif_cx = a640_gbif, .gmu_cgc_mode = 0x00020200, .prim_fifo_threshold = 0x00010000, }, - .address_space_size = SZ_16G, .speedbins = ADRENO_SPEEDBINS( { 0, 0 }, { 137, 1 }, ), }, { + .chip_ids = ADRENO_CHIP_IDS(0x06020300), + .family = ADRENO_6XX_GEN3, + .fw = { + [ADRENO_FW_SQE] = "a650_sqe.fw", + [ADRENO_FW_GMU] = "a623_gmu.bin", + }, + .gmem = SZ_512K, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_HAS_HW_APRIV, + .funcs = &a6xx_gpu_funcs, + .a6xx = &(const struct a6xx_info) { + .hwcg = a690_hwcg, + .protect = &a650_protect, + .gbif_cx = a640_gbif, + .gmu_cgc_mode = 0x00020200, + .prim_fifo_threshold = 0x00010000, + .bcms = (const struct a6xx_bcm[]) { + { .name = "SH0", .buswidth = 16 }, + { .name = "MC0", .buswidth = 4 }, + { + .name = "ACV", + .fixed = true, + .perfmode = BIT(3), + }, + { /* sentinel */ }, + }, + }, + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 185, 0 }, + { 127, 1 }, + ), + }, { .chip_ids = ADRENO_CHIP_IDS( 0x06030001, 0x06030002 @@ -891,9 +957,10 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a630_gmu.bin", }, .gmem = SZ_1M, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a630_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a630_hwcg, @@ -910,9 +977,10 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a640_gmu.bin", }, .gmem = SZ_1M, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a640_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a640_hwcg, @@ -936,15 +1004,15 @@ static const struct adreno_info a6xx_gpus[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | ADRENO_QUIRK_HAS_HW_APRIV, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a650_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a650_hwcg, .protect = &a650_protect, + .gbif_cx = a640_gbif, .gmu_cgc_mode = 0x00020202, .prim_fifo_threshold = 0x00300200, }, - .address_space_size = SZ_16G, .speedbins = ADRENO_SPEEDBINS( { 0, 0 }, { 1, 1 }, @@ -963,15 +1031,15 @@ static const struct adreno_info a6xx_gpus[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | ADRENO_QUIRK_HAS_HW_APRIV, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a660_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a660_hwcg, .protect = &a660_protect, + .gbif_cx = a640_gbif, .gmu_cgc_mode = 0x00020000, .prim_fifo_threshold = 0x00300200, }, - .address_space_size = SZ_16G, }, { .chip_ids = ADRENO_CHIP_IDS(0x06060300), .family = ADRENO_6XX_GEN4, @@ -983,14 +1051,19 @@ static const struct adreno_info a6xx_gpus[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | ADRENO_QUIRK_HAS_HW_APRIV, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .a6xx = &(const struct a6xx_info) { .hwcg = a690_hwcg, .protect = &a660_protect, + .gbif_cx = a640_gbif, .gmu_cgc_mode = 0x00020200, .prim_fifo_threshold = 0x00300200, }, - .address_space_size = SZ_16G, + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 169, 0 }, + { 113, 1 }, + ), }, { .chip_ids = ADRENO_CHIP_IDS(0x06030500), .family = ADRENO_6XX_GEN4, @@ -1002,15 +1075,15 @@ static const struct adreno_info a6xx_gpus[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | ADRENO_QUIRK_HAS_HW_APRIV, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a660_zap.mbn", .a6xx = &(const struct a6xx_info) { .hwcg = a660_hwcg, .protect = &a660_protect, + .gbif_cx = a640_gbif, .gmu_cgc_mode = 0x00020202, .prim_fifo_threshold = 0x00200200, }, - .address_space_size = SZ_16G, .speedbins = ADRENO_SPEEDBINS( { 0, 0 }, { 117, 0 }, @@ -1027,9 +1100,10 @@ static const struct adreno_info a6xx_gpus[] = { [ADRENO_FW_GMU] = "a640_gmu.bin", }, .gmem = SZ_2M, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_4GB_VA, .inactive_period = DRM_MSM_INACTIVE_PERIOD, - .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a640_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a640_hwcg, @@ -1048,30 +1122,19 @@ static const struct adreno_info a6xx_gpus[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | ADRENO_QUIRK_HAS_HW_APRIV, - .init = a6xx_gpu_init, + .funcs = &a6xx_gpu_funcs, .zapfw = "a690_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a690_hwcg, .protect = &a690_protect, + .gbif_cx = a640_gbif, .gmu_cgc_mode = 0x00020200, .prim_fifo_threshold = 0x00800200, }, - .address_space_size = SZ_16G, } }; DECLARE_ADRENO_GPULIST(a6xx); -MODULE_FIRMWARE("qcom/a615_zap.mbn"); -MODULE_FIRMWARE("qcom/a619_gmu.bin"); -MODULE_FIRMWARE("qcom/a630_sqe.fw"); -MODULE_FIRMWARE("qcom/a630_gmu.bin"); -MODULE_FIRMWARE("qcom/a630_zap.mbn"); -MODULE_FIRMWARE("qcom/a640_gmu.bin"); -MODULE_FIRMWARE("qcom/a650_gmu.bin"); -MODULE_FIRMWARE("qcom/a650_sqe.fw"); -MODULE_FIRMWARE("qcom/a660_gmu.bin"); -MODULE_FIRMWARE("qcom/a660_sqe.fw"); - static const struct adreno_reglist a702_hwcg[] = { { REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222 }, { REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220 }, @@ -1314,7 +1377,7 @@ static const uint32_t a7xx_pwrup_reglist_regs[] = { REG_A6XX_RB_NC_MODE_CNTL, REG_A6XX_RB_CMP_DBG_ECO_CNTL, REG_A7XX_GRAS_NC_MODE_CNTL, - REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE, + REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE, REG_A6XX_UCHE_GBIF_GX_CONFIG, REG_A6XX_UCHE_CLIENT_PF, REG_A6XX_TPL1_DBG_ECO_CNTL1, @@ -1322,6 +1385,69 @@ static const uint32_t a7xx_pwrup_reglist_regs[] = { DECLARE_ADRENO_REGLIST_LIST(a7xx_pwrup_reglist); +/* Applicable for X185, A750 */ +static const u32 a750_ifpc_reglist_regs[] = { + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(0), + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(1), + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(2), + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(3), + REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(4), + REG_A6XX_TPL1_NC_MODE_CNTL, + REG_A6XX_SP_NC_MODE_CNTL, + REG_A6XX_CP_DBG_ECO_CNTL, + REG_A6XX_CP_PROTECT_CNTL, + REG_A6XX_CP_PROTECT(0), + REG_A6XX_CP_PROTECT(1), + REG_A6XX_CP_PROTECT(2), + REG_A6XX_CP_PROTECT(3), + REG_A6XX_CP_PROTECT(4), + REG_A6XX_CP_PROTECT(5), + REG_A6XX_CP_PROTECT(6), + REG_A6XX_CP_PROTECT(7), + REG_A6XX_CP_PROTECT(8), + REG_A6XX_CP_PROTECT(9), + REG_A6XX_CP_PROTECT(10), + REG_A6XX_CP_PROTECT(11), + REG_A6XX_CP_PROTECT(12), + REG_A6XX_CP_PROTECT(13), + REG_A6XX_CP_PROTECT(14), + REG_A6XX_CP_PROTECT(15), + REG_A6XX_CP_PROTECT(16), + REG_A6XX_CP_PROTECT(17), + REG_A6XX_CP_PROTECT(18), + REG_A6XX_CP_PROTECT(19), + REG_A6XX_CP_PROTECT(20), + REG_A6XX_CP_PROTECT(21), + REG_A6XX_CP_PROTECT(22), + REG_A6XX_CP_PROTECT(23), + REG_A6XX_CP_PROTECT(24), + REG_A6XX_CP_PROTECT(25), + REG_A6XX_CP_PROTECT(26), + REG_A6XX_CP_PROTECT(27), + REG_A6XX_CP_PROTECT(28), + REG_A6XX_CP_PROTECT(29), + REG_A6XX_CP_PROTECT(30), + REG_A6XX_CP_PROTECT(31), + REG_A6XX_CP_PROTECT(32), + REG_A6XX_CP_PROTECT(33), + REG_A6XX_CP_PROTECT(34), + REG_A6XX_CP_PROTECT(35), + REG_A6XX_CP_PROTECT(36), + REG_A6XX_CP_PROTECT(37), + REG_A6XX_CP_PROTECT(38), + REG_A6XX_CP_PROTECT(39), + REG_A6XX_CP_PROTECT(40), + REG_A6XX_CP_PROTECT(41), + REG_A6XX_CP_PROTECT(42), + REG_A6XX_CP_PROTECT(43), + REG_A6XX_CP_PROTECT(44), + REG_A6XX_CP_PROTECT(45), + REG_A6XX_CP_PROTECT(46), + REG_A6XX_CP_PROTECT(47), +}; + +DECLARE_ADRENO_REGLIST_LIST(a750_ifpc_reglist); + static const struct adreno_info a7xx_gpus[] = { { .chip_ids = ADRENO_CHIP_IDS(0x07000200), @@ -1332,11 +1458,12 @@ static const struct adreno_info a7xx_gpus[] = { .gmem = SZ_128K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, .quirks = ADRENO_QUIRK_HAS_HW_APRIV, - .init = a6xx_gpu_init, + .funcs = &a6xx_gmuwrapper_funcs, .zapfw = "a702_zap.mbn", .a6xx = &(const struct a6xx_info) { .hwcg = a702_hwcg, .protect = &a650_protect, + .gbif_cx = a640_gbif, .gmu_cgc_mode = 0x00020202, .prim_fifo_threshold = 0x0000c000, }, @@ -1358,15 +1485,15 @@ static const struct adreno_info a7xx_gpus[] = { .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | ADRENO_QUIRK_HAS_HW_APRIV | ADRENO_QUIRK_PREEMPTION, - .init = a6xx_gpu_init, + .funcs = &a7xx_gpu_funcs, .zapfw = "a730_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a730_hwcg, .protect = &a730_protect, .pwrup_reglist = &a7xx_pwrup_reglist, + .gbif_cx = a640_gbif, .gmu_cgc_mode = 0x00020000, }, - .address_space_size = SZ_16G, .preempt_record_size = 2860 * SZ_1K, }, { .chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */ @@ -1380,16 +1507,27 @@ static const struct adreno_info a7xx_gpus[] = { .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | ADRENO_QUIRK_HAS_HW_APRIV | ADRENO_QUIRK_PREEMPTION, - .init = a6xx_gpu_init, + .funcs = &a7xx_gpu_funcs, .zapfw = "a740_zap.mdt", .a6xx = &(const struct a6xx_info) { .hwcg = a740_hwcg, .protect = &a730_protect, .pwrup_reglist = &a7xx_pwrup_reglist, + .gbif_cx = a640_gbif, .gmu_chipid = 0x7020100, .gmu_cgc_mode = 0x00020202, + .bcms = (const struct a6xx_bcm[]) { + { .name = "SH0", .buswidth = 16 }, + { .name = "MC0", .buswidth = 4 }, + { + .name = "ACV", + .fixed = true, + .perfmode = BIT(3), + .perfmode_bw = 16500000, + }, + { /* sentinel */ }, + }, }, - .address_space_size = SZ_16G, .preempt_record_size = 4192 * SZ_1K, }, { .chip_ids = ADRENO_CHIP_IDS(0x43050c01), /* "C512v2" */ @@ -1402,17 +1540,37 @@ static const struct adreno_info a7xx_gpus[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | ADRENO_QUIRK_HAS_HW_APRIV | - ADRENO_QUIRK_PREEMPTION, - .init = a6xx_gpu_init, + ADRENO_QUIRK_PREEMPTION | + ADRENO_QUIRK_IFPC, + .funcs = &a7xx_gpu_funcs, .a6xx = &(const struct a6xx_info) { .hwcg = a740_hwcg, .protect = &a730_protect, .pwrup_reglist = &a7xx_pwrup_reglist, + .ifpc_reglist = &a750_ifpc_reglist, + .gbif_cx = a640_gbif, .gmu_chipid = 0x7050001, .gmu_cgc_mode = 0x00020202, + .bcms = (const struct a6xx_bcm[]) { + { .name = "SH0", .buswidth = 16 }, + { .name = "MC0", .buswidth = 4 }, + { + .name = "ACV", + .fixed = true, + .perfmode = BIT(3), + .perfmode_bw = 16500000, + }, + { /* sentinel */ }, + }, }, - .address_space_size = SZ_256G, .preempt_record_size = 4192 * SZ_1K, + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 59, 1 }, + { 7, 2 }, + { 232, 3 }, + { 146, 4 }, + ), }, { .chip_ids = ADRENO_CHIP_IDS(0x43051401), /* "C520v2" */ .family = ADRENO_7XX_GEN3, @@ -1424,21 +1582,374 @@ static const struct adreno_info a7xx_gpus[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | ADRENO_QUIRK_HAS_HW_APRIV | - ADRENO_QUIRK_PREEMPTION, - .init = a6xx_gpu_init, + ADRENO_QUIRK_PREEMPTION | + ADRENO_QUIRK_IFPC, + .funcs = &a7xx_gpu_funcs, .zapfw = "gen70900_zap.mbn", .a6xx = &(const struct a6xx_info) { .protect = &a730_protect, .pwrup_reglist = &a7xx_pwrup_reglist, + .ifpc_reglist = &a750_ifpc_reglist, + .gbif_cx = a640_gbif, .gmu_chipid = 0x7090100, .gmu_cgc_mode = 0x00020202, + .bcms = (const struct a6xx_bcm[]) { + { .name = "SH0", .buswidth = 16 }, + { .name = "MC0", .buswidth = 4 }, + { + .name = "ACV", + .fixed = true, + .perfmode = BIT(2), + .perfmode_bw = 10687500, + }, + { /* sentinel */ }, + }, }, - .address_space_size = SZ_16G, .preempt_record_size = 3572 * SZ_1K, + }, { + .chip_ids = ADRENO_CHIP_IDS(0x43030c00), + .family = ADRENO_7XX_GEN2, + .fw = { + [ADRENO_FW_SQE] = "gen71500_sqe.fw", + [ADRENO_FW_GMU] = "gen71500_gmu.bin", + }, + .gmem = SZ_1M + SZ_512K, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_HAS_HW_APRIV | + ADRENO_QUIRK_PREEMPTION, + .funcs = &a7xx_gpu_funcs, + .a6xx = &(const struct a6xx_info) { + .hwcg = a740_hwcg, + .protect = &a730_protect, + .pwrup_reglist = &a7xx_pwrup_reglist, + .gbif_cx = a640_gbif, + .gmu_chipid = 0x70f0000, + .gmu_cgc_mode = 0x00020222, + .bcms = (const struct a6xx_bcm[]) { + { .name = "SH0", .buswidth = 16 }, + { .name = "MC0", .buswidth = 4 }, + { + .name = "ACV", + .fixed = true, + .perfmode = BIT(3), + .perfmode_bw = 16500000, + }, + { /* sentinel */ }, + }, + }, + .preempt_record_size = 4192 * SZ_1K, + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 294, 1 }, + { 263, 2 }, + { 233, 3 }, + { 141, 4 }, + ), } }; DECLARE_ADRENO_GPULIST(a7xx); +static const struct adreno_reglist_pipe x285_nonctxt_regs[] = { + { REG_A8XX_CP_SMMU_STREAM_ID_LPAC, 0x00000101, BIT(PIPE_NONE) }, + { REG_A8XX_GRAS_DBG_ECO_CNTL, 0x00000800, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_GRAS_TSEFE_DBG_ECO_CNTL, 0x00200000, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A6XX_PC_AUTO_VERTEX_STRIDE, 0x00000001, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_VIS_STREAM_CNTL, 0x10010000, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_CONTEXT_SWITCH_STABILIZE_CNTL_1, 0x00000002, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_CHICKEN_BITS_1, 0x00000003, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_CHICKEN_BITS_2, 0x00000200, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_CHICKEN_BITS_3, 0x00500000, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_CHICKEN_BITS_4, 0x00500050, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_RB_GC_GMEM_PROTECT, 0x15000000, BIT(PIPE_BR) }, + { REG_A8XX_RB_RESOLVE_PREFETCH_CNTL, 0x00000007, BIT(PIPE_BR) }, + { REG_A8XX_RB_CMP_DBG_ECO_CNTL, 0x00004000, BIT(PIPE_BR) }, + { REG_A8XX_RBBM_NC_MODE_CNTL, 0x00000001, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_SLICE_NC_MODE_CNTL, 0x00000001, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_WAIT_IDLE_CLOCKS_CNTL, 0x00000030, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_WAIT_IDLE_CLOCKS_CNTL2, 0x00000030, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_INTERFACE_HANG_INT_CNTL, 0x0fffffff, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x22122212, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_CGC_P2S_CNTL, 0x00000040, BIT(PIPE_NONE) }, + { REG_A7XX_SP_CHICKEN_BITS_2, 0x00820800, BIT(PIPE_NONE) }, + { REG_A7XX_SP_CHICKEN_BITS_3, 0x00300000, BIT(PIPE_NONE) }, + { REG_A6XX_SP_PERFCTR_SHADER_MASK, 0x0000003f, BIT(PIPE_NONE) }, + /* Disable CS dead batch merge */ + { REG_A7XX_SP_HLSQ_DBG_ECO_CNTL_2, BIT(31), BIT(PIPE_NONE) }, + { REG_A7XX_SP_HLSQ_TIMEOUT_THRESHOLD_DP, 0x00000080, BIT(PIPE_NONE) }, + { REG_A7XX_SP_READ_SEL, 0x0001ff00, BIT(PIPE_NONE) }, + { REG_A6XX_TPL1_DBG_ECO_CNTL, 0x10000000, BIT(PIPE_NONE) }, + /* BIT(26): Disable final clamp for bicubic filtering */ + { REG_A6XX_TPL1_DBG_ECO_CNTL1, 0x00000720, BIT(PIPE_NONE) }, + { REG_A6XX_UCHE_MODE_CNTL, 0x80080000, BIT(PIPE_NONE) }, + { REG_A8XX_UCHE_CCHE_MODE_CNTL, 0x00001000, BIT(PIPE_NONE) }, + { REG_A8XX_UCHE_CCHE_CACHE_WAYS, 0x00000800, BIT(PIPE_NONE) }, + { REG_A8XX_UCHE_GBIF_GX_CONFIG, 0x010240e0, BIT(PIPE_NONE) }, + { REG_A8XX_UCHE_VARB_IDLE_TIMEOUT, 0x00000020, BIT(PIPE_NONE) }, + { REG_A7XX_VFD_DBG_ECO_CNTL, 0x00008000, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_VFD_CB_BV_THRESHOLD, 0x00500050, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_VFD_CB_BR_THRESHOLD, 0x00600060, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_VFD_CB_BUSY_REQ_CNT, 0x00200020, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_VFD_CB_LP_REQ_CNT, 0x00000020, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_VPC_FLATSHADE_MODE_CNTL, 0x00000001, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { }, +}; + +static const u32 x285_protect_regs[] = { + A6XX_PROTECT_RDONLY(0x00008, 0x039b), + A6XX_PROTECT_RDONLY(0x003b4, 0x008b), + A6XX_PROTECT_NORDWR(0x00440, 0x001f), + A6XX_PROTECT_RDONLY(0x00580, 0x005f), + A6XX_PROTECT_NORDWR(0x005e0, 0x011f), + A6XX_PROTECT_RDONLY(0x0074a, 0x0005), + A6XX_PROTECT_RDONLY(0x00759, 0x0026), + A6XX_PROTECT_RDONLY(0x00789, 0x0000), + A6XX_PROTECT_RDONLY(0x0078c, 0x0013), + A6XX_PROTECT_NORDWR(0x00800, 0x0029), + A6XX_PROTECT_NORDWR(0x0082c, 0x0000), + A6XX_PROTECT_NORDWR(0x00837, 0x00af), + A6XX_PROTECT_RDONLY(0x008e7, 0x00c9), + A6XX_PROTECT_NORDWR(0x008ec, 0x00c3), + A6XX_PROTECT_NORDWR(0x009b1, 0x0250), + A6XX_PROTECT_RDONLY(0x00ce0, 0x0001), + A6XX_PROTECT_RDONLY(0x00df0, 0x0000), + A6XX_PROTECT_NORDWR(0x00df1, 0x0000), + A6XX_PROTECT_NORDWR(0x00e01, 0x0000), + A6XX_PROTECT_NORDWR(0x00e03, 0x1fff), + A6XX_PROTECT_NORDWR(0x03c00, 0x00c5), + A6XX_PROTECT_RDONLY(0x03cc6, 0x0039), + A6XX_PROTECT_NORDWR(0x03d00, 0x1fff), + A6XX_PROTECT_NORDWR(0x08600, 0x01ff), + A6XX_PROTECT_NORDWR(0x08e00, 0x00ff), + A6XX_PROTECT_RDONLY(0x08f00, 0x0000), + A6XX_PROTECT_NORDWR(0x08f01, 0x01be), + A6XX_PROTECT_NORDWR(0x09600, 0x01ff), + A6XX_PROTECT_RDONLY(0x0981a, 0x02e5), + A6XX_PROTECT_NORDWR(0x09e00, 0x01ff), + A6XX_PROTECT_NORDWR(0x0a600, 0x01ff), + A6XX_PROTECT_NORDWR(0x0a82e, 0x0000), + A6XX_PROTECT_NORDWR(0x0ae00, 0x0006), + A6XX_PROTECT_NORDWR(0x0ae08, 0x0006), + A6XX_PROTECT_NORDWR(0x0ae10, 0x00bf), + A6XX_PROTECT_RDONLY(0x0aed0, 0x002f), + A6XX_PROTECT_NORDWR(0x0af00, 0x027f), + A6XX_PROTECT_NORDWR(0x0b600, 0x1fff), + A6XX_PROTECT_NORDWR(0x0dc00, 0x1fff), + A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff), + A6XX_PROTECT_NORDWR(0x18400, 0x003f), + A6XX_PROTECT_RDONLY(0x18440, 0x013f), + A6XX_PROTECT_NORDWR(0x18580, 0x1fff), + A6XX_PROTECT_NORDWR(0x1b400, 0x1fff), + A6XX_PROTECT_NORDWR(0x1f400, 0x0477), + A6XX_PROTECT_RDONLY(0x1f878, 0x0507), + A6XX_PROTECT_NORDWR(0x1f930, 0x0329), + A6XX_PROTECT_NORDWR(0x1fd80, 0x1fff), + A6XX_PROTECT_NORDWR(0x27800, 0x007f), + A6XX_PROTECT_RDONLY(0x27880, 0x0385), + A6XX_PROTECT_NORDWR(0x27882, 0x000a), + A6XX_PROTECT_NORDWR(0x27c06, 0x0000), +}; + +DECLARE_ADRENO_PROTECT(x285_protect, 64); + +static const struct adreno_reglist_pipe a840_nonctxt_regs[] = { + { REG_A8XX_CP_SMMU_STREAM_ID_LPAC, 0x00000101, BIT(PIPE_NONE) }, + { REG_A8XX_GRAS_DBG_ECO_CNTL, 0x00000800, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_GRAS_TSEFE_DBG_ECO_CNTL, 0x00200000, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A6XX_PC_AUTO_VERTEX_STRIDE, 0x00000001, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_VIS_STREAM_CNTL, 0x10010000, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_CONTEXT_SWITCH_STABILIZE_CNTL_1, 0x00000002, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_CHICKEN_BITS_1, 0x00000003, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_CHICKEN_BITS_2, 0x00000200, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_CHICKEN_BITS_3, 0x00500000, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_PC_CHICKEN_BITS_4, 0x00500050, BIT(PIPE_BV) | BIT(PIPE_BR) }, + /* Disable Dead Draw Merge scheme on RB-HLSQ */ + { REG_A6XX_RB_RBP_CNTL, BIT(5), BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A7XX_RB_CCU_CNTL, 0x00000068, BIT(PIPE_BR) }, + /* Partially enable perf clear, Disable DINT to c/z be data forwarding */ + { REG_A7XX_RB_CCU_DBG_ECO_CNTL, 0x00002200, BIT(PIPE_BR) }, + { REG_A8XX_RB_GC_GMEM_PROTECT, 0x12000000, BIT(PIPE_BR) }, + { REG_A8XX_RB_RESOLVE_PREFETCH_CNTL, 0x00000007, BIT(PIPE_BR) }, + { REG_A8XX_RB_CMP_DBG_ECO_CNTL, 0x00004000, BIT(PIPE_BR) }, + { REG_A8XX_RBBM_NC_MODE_CNTL, 0x00000001, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_SLICE_NC_MODE_CNTL, 0x00000001, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_POWER_UP_RESET_SW_OVERRIDE, 0x70809060, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_POWER_UP_RESET_SW_BV_OVERRIDE, 0x30000000, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_WAIT_IDLE_CLOCKS_CNTL, 0x00000030, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_WAIT_IDLE_CLOCKS_CNTL2, 0x00000030, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_INTERFACE_HANG_INT_CNTL, 0x0fffffff, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x22122212, BIT(PIPE_NONE) }, + { REG_A8XX_RBBM_CGC_P2S_CNTL, 0x00000040, BIT(PIPE_NONE) }, + /* Disable mode_switch optimization in UMAS */ + { REG_A6XX_SP_CHICKEN_BITS, BIT(24) | BIT(26), BIT(PIPE_NONE) }, + /* Disable LPAC large-LM mode */ + { REG_A8XX_SP_SS_CHICKEN_BITS_0, BIT(3), BIT(PIPE_NONE) }, + /* Disable PS out of order retire */ + { REG_A7XX_SP_CHICKEN_BITS_2, 0x00c21800, BIT(PIPE_NONE) }, + { REG_A7XX_SP_CHICKEN_BITS_3, 0x00300000, BIT(PIPE_NONE) }, + /* Disable SP2TP info attribute */ + { REG_A8XX_SP_CHICKEN_BITS_4, 0x00000002, BIT(PIPE_NONE) }, + { REG_A6XX_SP_PERFCTR_SHADER_MASK, 0x0000003f, BIT(PIPE_NONE) }, + { REG_A7XX_SP_HLSQ_DBG_ECO_CNTL, BIT(14), BIT(PIPE_NONE) }, + /* Ignore HLSQ shared constant feedback from SP */ + { REG_A7XX_SP_HLSQ_DBG_ECO_CNTL_1, BIT(17), BIT(PIPE_NONE) }, + /* Disable CS dead batch merge */ + { REG_A7XX_SP_HLSQ_DBG_ECO_CNTL_2, BIT(24), BIT(PIPE_NONE) }, + { REG_A8XX_SP_HLSQ_DBG_ECO_CNTL_3, BIT(7), BIT(PIPE_NONE) }, + { REG_A7XX_SP_HLSQ_TIMEOUT_THRESHOLD_DP, 0x00000080, BIT(PIPE_NONE) }, + { REG_A7XX_SP_READ_SEL, 0x0001ff00, BIT(PIPE_NONE) }, + { REG_A6XX_TPL1_DBG_ECO_CNTL, 0x10100000, BIT(PIPE_NONE) }, + /* BIT(26): Disable final clamp for bicubic filtering */ + { REG_A6XX_TPL1_DBG_ECO_CNTL1, 0x04000720, BIT(PIPE_NONE) }, + { REG_A6XX_UCHE_MODE_CNTL, 0x80080000, BIT(PIPE_NONE) }, + { REG_A8XX_UCHE_CCHE_MODE_CNTL, 0x00001000, BIT(PIPE_NONE) }, + { REG_A8XX_UCHE_CCHE_CACHE_WAYS, 0x00000800, BIT(PIPE_NONE) }, + { REG_A8XX_UCHE_GBIF_GX_CONFIG, 0x010240e0, BIT(PIPE_NONE) }, + { REG_A8XX_UCHE_VARB_IDLE_TIMEOUT, 0x00000020, BIT(PIPE_NONE) }, + { REG_A7XX_VFD_DBG_ECO_CNTL, 0x00008000, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_VFD_CB_BV_THRESHOLD, 0x00500050, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_VFD_CB_BR_THRESHOLD, 0x00600060, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_VFD_CB_BUSY_REQ_CNT, 0x00200020, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_VFD_CB_LP_REQ_CNT, 0x00000020, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { REG_A8XX_VPC_FLATSHADE_MODE_CNTL, 0x00000001, BIT(PIPE_BV) | BIT(PIPE_BR) }, + { }, +}; + +static const u32 a840_protect_regs[] = { + A6XX_PROTECT_RDONLY(0x00008, 0x039b), + A6XX_PROTECT_RDONLY(0x003b4, 0x008b), + A6XX_PROTECT_NORDWR(0x00440, 0x001f), + A6XX_PROTECT_RDONLY(0x00580, 0x005f), + A6XX_PROTECT_NORDWR(0x005e0, 0x011f), + A6XX_PROTECT_RDONLY(0x0074a, 0x0005), + A6XX_PROTECT_RDONLY(0x00759, 0x001b), + A6XX_PROTECT_NORDWR(0x00775, 0x000a), + A6XX_PROTECT_RDONLY(0x00789, 0x0000), + A6XX_PROTECT_RDONLY(0x0078c, 0x0013), + A6XX_PROTECT_NORDWR(0x00800, 0x0029), + A6XX_PROTECT_NORDWR(0x00837, 0x00af), + A6XX_PROTECT_RDONLY(0x008e7, 0x00c9), + A6XX_PROTECT_NORDWR(0x008ec, 0x00c3), + A6XX_PROTECT_NORDWR(0x009b1, 0x0250), + A6XX_PROTECT_NORDWR(0x00c07, 0x0008), + A6XX_PROTECT_RDONLY(0x00ce0, 0x0001), + A6XX_PROTECT_RDONLY(0x00df0, 0x0000), + A6XX_PROTECT_NORDWR(0x00df1, 0x0000), + A6XX_PROTECT_NORDWR(0x00e01, 0x0000), + A6XX_PROTECT_NORDWR(0x00e03, 0x1fff), + A6XX_PROTECT_NORDWR(0x03c00, 0x00c5), + A6XX_PROTECT_RDONLY(0x03cc6, 0x0039), + A6XX_PROTECT_NORDWR(0x03d00, 0x1fff), + A6XX_PROTECT_NORDWR(0x08600, 0x01ff), + A6XX_PROTECT_NORDWR(0x08e00, 0x00ff), + A6XX_PROTECT_RDONLY(0x08f00, 0x0000), + A6XX_PROTECT_NORDWR(0x08f01, 0x01be), + A6XX_PROTECT_NORDWR(0x09600, 0x01ff), + A6XX_PROTECT_RDONLY(0x0981a, 0x02e5), + A6XX_PROTECT_NORDWR(0x09e00, 0x01ff), + A6XX_PROTECT_NORDWR(0x0a600, 0x01ff), + A6XX_PROTECT_NORDWR(0x0a82e, 0x0000), + A6XX_PROTECT_NORDWR(0x0ae00, 0x0000), + A6XX_PROTECT_NORDWR(0x0ae02, 0x0004), + A6XX_PROTECT_NORDWR(0x0ae08, 0x0006), + A6XX_PROTECT_NORDWR(0x0ae10, 0x00bf), + A6XX_PROTECT_RDONLY(0x0aed0, 0x002f), + A6XX_PROTECT_NORDWR(0x0af00, 0x027f), + A6XX_PROTECT_NORDWR(0x0b600, 0x1fff), + A6XX_PROTECT_NORDWR(0x0dc00, 0x1fff), + A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff), + A6XX_PROTECT_NORDWR(0x18400, 0x003f), + A6XX_PROTECT_RDONLY(0x18440, 0x013f), + A6XX_PROTECT_NORDWR(0x18580, 0x1fff), + A6XX_PROTECT_NORDWR(0x1b400, 0x1fff), + A6XX_PROTECT_NORDWR(0x1f400, 0x0477), + A6XX_PROTECT_RDONLY(0x1f878, 0x0507), + A6XX_PROTECT_NORDWR(0x1f930, 0x0329), + A6XX_PROTECT_NORDWR(0x1fd80, 0x1fff), + A6XX_PROTECT_NORDWR(0x27800, 0x007f), + A6XX_PROTECT_RDONLY(0x27880, 0x0385), + A6XX_PROTECT_NORDWR(0x27882, 0x0009), + A6XX_PROTECT_NORDWR(0x27c06, 0x0000), +}; +DECLARE_ADRENO_PROTECT(a840_protect, 15); + +static const struct adreno_reglist a840_gbif[] = { + { REG_A6XX_GBIF_QSB_SIDE0, 0x00071e20 }, + { REG_A6XX_GBIF_QSB_SIDE1, 0x00071e20 }, + { REG_A6XX_GBIF_QSB_SIDE2, 0x00071e20 }, + { REG_A6XX_GBIF_QSB_SIDE3, 0x00071e20 }, + { REG_A8XX_GBIF_CX_CONFIG, 0x20023000 }, + { }, +}; + +static const struct adreno_info a8xx_gpus[] = { + { + .chip_ids = ADRENO_CHIP_IDS(0x44070001), + .family = ADRENO_8XX_GEN2, + .fw = { + [ADRENO_FW_SQE] = "gen80100_sqe.fw", + [ADRENO_FW_GMU] = "gen80100_gmu.bin", + }, + .gmem = 21 * SZ_1M, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_HAS_HW_APRIV, + .funcs = &a8xx_gpu_funcs, + .a6xx = &(const struct a6xx_info) { + .protect = &x285_protect, + .nonctxt_reglist = x285_nonctxt_regs, + .gbif_cx = a840_gbif, + .max_slices = 4, + .gmu_chipid = 0x8010100, + .bcms = (const struct a6xx_bcm[]) { + { .name = "SH0", .buswidth = 16 }, + { .name = "MC0", .buswidth = 4 }, + { + .name = "ACV", + .fixed = true, + .perfmode = BIT(2), + .perfmode_bw = 16500000, + }, + { /* sentinel */ }, + }, + }, + }, { + .chip_ids = ADRENO_CHIP_IDS(0x44050a01), + .family = ADRENO_8XX_GEN2, + .fw = { + [ADRENO_FW_SQE] = "gen80200_sqe.fw", + [ADRENO_FW_GMU] = "gen80200_gmu.bin", + [ADRENO_FW_AQE] = "gen80200_aqe.fw", + }, + .gmem = 18 * SZ_1M, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_HAS_HW_APRIV, + .funcs = &a8xx_gpu_funcs, + .a6xx = &(const struct a6xx_info) { + .protect = &a840_protect, + .nonctxt_reglist = a840_nonctxt_regs, + .gbif_cx = a840_gbif, + .max_slices = 3, + .gmu_chipid = 0x8020100, + .bcms = (const struct a6xx_bcm[]) { + { .name = "SH0", .buswidth = 16 }, + { .name = "MC0", .buswidth = 4 }, + { + .name = "ACV", + .fixed = true, + .perfmode = BIT(2), + .perfmode_bw = 10687500, + }, + { /* sentinel */ }, + }, + }, + .preempt_record_size = 19708 * SZ_1K, + } +}; + +DECLARE_ADRENO_GPULIST(a8xx); + static inline __always_unused void __build_asserts(void) { BUILD_BUG_ON(a630_protect.count > a630_protect.count_max); @@ -1446,4 +1957,5 @@ static inline __always_unused void __build_asserts(void) BUILD_BUG_ON(a660_protect.count > a660_protect.count_max); BUILD_BUG_ON(a690_protect.count > a690_protect.count_max); BUILD_BUG_ON(a730_protect.count > a730_protect.count_max); + BUILD_BUG_ON(a840_protect.count > a840_protect.count_max); } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 14db7376c712..5903cd891b49 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -9,6 +9,7 @@ #include <linux/pm_domain.h> #include <linux/pm_opp.h> #include <soc/qcom/cmd-db.h> +#include <soc/qcom/tcs.h> #include <drm/drm_gem.h> #include "a6xx_gpu.h" @@ -27,7 +28,7 @@ static void a6xx_gmu_fault(struct a6xx_gmu *gmu) gmu->hung = true; /* Turn off the hangcheck timer while we are resetting */ - del_timer(&gpu->hangcheck_timer); + timer_delete(&gpu->hangcheck_timer); /* Queue the GPU handler because we need to treat this as a recovery */ kthread_queue_work(gpu->worker, &gpu->recover_work); @@ -92,14 +93,25 @@ bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu) /* Check to see if the GX rail is still powered */ bool a6xx_gmu_gx_is_on(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 val; /* This can be called from gpu state code so make sure GMU is valid */ if (!gmu->initialized) return false; + /* If GMU is absent, then GX power domain is ON as long as GPU is in active state */ + if (adreno_has_gmu_wrapper(adreno_gpu)) + return true; + val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS); + if (adreno_is_a7xx(adreno_gpu)) + return !(val & + (A7XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF | + A7XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF)); + return !(val & (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF | A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF)); @@ -109,9 +121,11 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, bool suspended) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + const struct a6xx_info *info = adreno_gpu->info->a6xx; struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); struct a6xx_gmu *gmu = &a6xx_gpu->gmu; u32 perf_index; + u32 bw_index = 0; unsigned long gpu_freq; int ret = 0; @@ -124,6 +138,37 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, if (gpu_freq == gmu->gpu_freqs[perf_index]) break; + /* If enabled, find the corresponding DDR bandwidth index */ + if (info->bcms && gmu->nr_gpu_bws > 1) { + unsigned int bw = dev_pm_opp_get_bw(opp, true, 0); + + for (bw_index = 0; bw_index < gmu->nr_gpu_bws - 1; bw_index++) { + if (bw == gmu->gpu_bw_table[bw_index]) + break; + } + + /* Vote AB as a fraction of the max bandwidth, starting from A750 */ + if (bw && adreno_is_a750_family(adreno_gpu)) { + u64 tmp; + + /* For now, vote for 25% of the bandwidth */ + tmp = bw * 25; + do_div(tmp, 100); + + /* + * The AB vote consists of a 16 bit wide quantized level + * against the maximum supported bandwidth. + * Quantization can be calculated as below: + * vote = (bandwidth * 2^16) / max bandwidth + */ + tmp *= MAX_AB_VOTE; + do_div(tmp, gmu->gpu_bw_table[gmu->nr_gpu_bws - 1]); + + bw_index |= AB_VOTE(clamp(tmp, 1, MAX_AB_VOTE)); + bw_index |= AB_VOTE_ENABLE; + } + } + gmu->current_perf_index = perf_index; gmu->freq = gmu->gpu_freqs[perf_index]; @@ -139,8 +184,10 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, return; if (!gmu->legacy) { - a6xx_hfi_set_freq(gmu, perf_index); - dev_pm_opp_set_opp(&gpu->pdev->dev, opp); + a6xx_hfi_set_freq(gmu, perf_index, bw_index); + /* With Bandwidth voting, we now vote for all resources, so skip OPP set */ + if (!bw_index) + dev_pm_opp_set_opp(&gpu->pdev->dev, opp); return; } @@ -177,14 +224,19 @@ unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu) static bool a6xx_gmu_check_idle_level(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; int local = gmu->idle_level; + u32 val; /* SPTP and IFPC both report as IFPC */ if (gmu->idle_level == GMU_IDLE_STATE_SPTP) local = GMU_IDLE_STATE_IFPC; - val = gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE); + if (adreno_is_a8xx(adreno_gpu)) + val = gmu_read(gmu, REG_A8XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE); + else + val = gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE); if (val == local) { if (gmu->idle_level != GMU_IDLE_STATE_IFPC || @@ -222,7 +274,9 @@ 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 */ - if (adreno_is_a7xx(adreno_gpu)) + if (adreno_is_a8xx(adreno_gpu)) + gmu_write(gmu, REG_A8XX_GMU_GENERAL_9, 0); + else if (adreno_is_a7xx(adreno_gpu)) gmu_write(gmu, REG_A7XX_GMU_GENERAL_9, 0); else gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP, 0); @@ -236,6 +290,8 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu) if (ret) DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n"); + set_bit(GMU_STATUS_FW_START, &gmu->status); + return ret; } @@ -301,12 +357,18 @@ static const struct a6xx_gmu_oob_bits a6xx_gmu_oob_bits[] = { /* Trigger a OOB (out of band) request to the GMU */ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) { + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; int ret; u32 val; int request, ack; WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); + /* Skip OOB calls since RGMU is not enabled */ + if (adreno_has_rgmu(adreno_gpu)) + return 0; + if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) return -EINVAL; @@ -327,9 +389,23 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) /* Trigger the equested OOB operation */ gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, 1 << request); - /* Wait for the acknowledge interrupt */ - ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO, val, - val & (1 << ack), 100, 10000); + do { + /* Wait for the acknowledge interrupt */ + ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO, val, + val & (1 << ack), 100, 10000); + + if (!ret) + break; + + if (completion_done(&a6xx_gpu->base.fault_coredump_done)) + break; + + /* We may timeout because the GMU is temporarily wedged from + * pending faults from the GPU and we are taking a devcoredump. + * Wait until the MMU is resumed and try again. + */ + wait_for_completion(&a6xx_gpu->base.fault_coredump_done); + } while (true); if (ret) DRM_DEV_ERROR(gmu->dev, @@ -346,10 +422,16 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) /* Clear a pending OOB state in the GMU */ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) { + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; int bit; WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); + /* Skip OOB calls since RGMU is not enabled */ + if (adreno_has_rgmu(adreno_gpu)) + return; + if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) return; @@ -367,7 +449,10 @@ int a6xx_sptprac_enable(struct a6xx_gmu *gmu) int ret; u32 val; - if (!gmu->legacy) + WARN_ON(!gmu->legacy); + + /* Nothing to do if GMU does the power management */ + if (gmu->idle_level > GMU_IDLE_STATE_ACTIVE) return 0; gmu_write(gmu, REG_A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, 0x778000); @@ -433,17 +518,25 @@ static void a6xx_gemnoc_workaround(struct a6xx_gmu *gmu) * in the power down sequence not being fully executed. That in turn can * prevent CX_GDSC from collapsing. Assert Qactive to avoid this. */ - if (adreno_is_a621(adreno_gpu) || adreno_is_7c3(adreno_gpu)) - gmu_write(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, BIT(0)); + if (adreno_is_a8xx(adreno_gpu)) + gmu_write(gmu, REG_A8XX_GPU_GMU_CX_GMU_CX_FALNEXT_INTF, BIT(0)); + else if (adreno_is_a7xx(adreno_gpu) || (adreno_is_a621(adreno_gpu) || + adreno_is_7c3(adreno_gpu))) + gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_CX_FALNEXT_INTF, BIT(0)); } /* Let the GMU know that we are about to go into slumber */ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu) { + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; int ret; /* Disable the power counter so the GMU isn't busy */ - gmu_write(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0); + if (adreno_is_a8xx(adreno_gpu)) + gmu_write(gmu, REG_A8XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0); + else + gmu_write(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0); /* Disable SPTP_PC if the CPU is responsible for it */ if (gmu->idle_level < GMU_IDLE_STATE_SPTP) @@ -470,10 +563,9 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu) } out: - a6xx_gemnoc_workaround(gmu); - /* Put fence into allow mode */ gmu_write(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0); + a6xx_gemnoc_workaround(gmu); return ret; } @@ -482,6 +574,9 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu) int ret; u32 val; + if (!test_and_clear_bit(GMU_STATUS_PDC_SLEEP, &gmu->status)) + return 0; + gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, BIT(1)); ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val, @@ -506,17 +601,28 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu) static void a6xx_rpmh_stop(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 bitmask = BIT(16); int ret; u32 val; + if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status)) + return; + + if (adreno_is_a840(adreno_gpu)) + bitmask = BIT(30); + gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1); ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, - val, val & (1 << 16), 100, 10000); + val, val & bitmask, 100, 10000); if (ret) DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n"); gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0); + + set_bit(GMU_STATUS_PDC_SLEEP, &gmu->status); } static inline void pdc_write(void __iomem *ptr, u32 offset, u32 value) @@ -524,22 +630,24 @@ static inline void pdc_write(void __iomem *ptr, u32 offset, u32 value) writel(value, ptr + (offset << 2)); } -static void __iomem *a6xx_gmu_get_mmio(struct platform_device *pdev, - const char *name); - static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) { struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, 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; + void __iomem *pdcptr; bool pdc_in_aop = false; + /* On A8x and above, RPMH/PDC configurations are entirely configured in AOP */ + if (adreno_is_a8xx(adreno_gpu)) + return; + + pdcptr = devm_platform_ioremap_resource_byname(pdev, "gmu_pdc"); if (IS_ERR(pdcptr)) - goto err; + return; if (adreno_is_a650_family(adreno_gpu) || adreno_is_a7xx(adreno_gpu)) @@ -552,9 +660,9 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) pdc_address_offset = 0x30080; if (!pdc_in_aop) { - seqptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc_seq"); + seqptr = devm_platform_ioremap_resource_byname(pdev, "gmu_pdc_seq"); if (IS_ERR(seqptr)) - goto err; + return; } /* Disable SDE clock gating */ @@ -644,14 +752,6 @@ setup_pdc: /* ensure no writes happen before the uCode is fully written */ wmb(); - - a6xx_rpmh_stop(gmu); - -err: - if (!IS_ERR_OR_NULL(pdcptr)) - iounmap(pdcptr); - if (!IS_ERR_OR_NULL(seqptr)) - iounmap(seqptr); } /* @@ -674,7 +774,7 @@ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu) gmu_write(gmu, REG_A6XX_GMU_DCACHE_CONFIG, 0x1); /* A7xx knows better by default! */ - if (adreno_is_a7xx(adreno_gpu)) + if (adreno_is_a7xx(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) return; gmu_write(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0x9c40400); @@ -722,6 +822,9 @@ static bool fw_block_mem(struct a6xx_gmu_bo *bo, const struct block_header *blk) return true; } +#define NEXT_BLK(blk) \ + ((const struct block_header *)((const char *)(blk) + sizeof(*(blk)) + (blk)->size)) + static int a6xx_gmu_fw_load(struct a6xx_gmu *gmu) { struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); @@ -729,11 +832,14 @@ static int a6xx_gmu_fw_load(struct a6xx_gmu *gmu) const struct firmware *fw_image = adreno_gpu->fw[ADRENO_FW_GMU]; const struct block_header *blk; u32 reg_offset; + u32 ver; u32 itcm_base = 0x00000000; u32 dtcm_base = 0x00040000; - if (adreno_is_a650_family(adreno_gpu) || adreno_is_a7xx(adreno_gpu)) + if (adreno_is_a650_family(adreno_gpu) || + adreno_is_a7xx(adreno_gpu) || + adreno_is_a8xx(adreno_gpu)) dtcm_base = 0x10004000; if (gmu->legacy) { @@ -752,7 +858,7 @@ static int a6xx_gmu_fw_load(struct a6xx_gmu *gmu) for (blk = (const struct block_header *) fw_image->data; (const u8*) blk < fw_image->data + fw_image->size; - blk = (const struct block_header *) &blk->data[blk->size >> 2]) { + blk = NEXT_BLK(blk)) { if (blk->size == 0) continue; @@ -775,6 +881,12 @@ static int a6xx_gmu_fw_load(struct a6xx_gmu *gmu) } } + ver = gmu_read(gmu, REG_A6XX_GMU_CORE_FW_VERSION); + DRM_INFO_ONCE("Loaded GMU firmware v%u.%u.%u\n", + FIELD_GET(A6XX_GMU_CORE_FW_VERSION_MAJOR__MASK, ver), + FIELD_GET(A6XX_GMU_CORE_FW_VERSION_MINOR__MASK, ver), + FIELD_GET(A6XX_GMU_CORE_FW_VERSION_STEP__MASK, ver)); + return 0; } @@ -782,7 +894,9 @@ 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; + struct msm_gpu *gpu = &adreno_gpu->base; const struct a6xx_info *a6xx_info = adreno_gpu->info->a6xx; + const struct adreno_reglist *gbif_cx = a6xx_info->gbif_cx; u32 fence_range_lower, fence_range_upper; u32 chipid = 0; int ret; @@ -791,27 +905,26 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) 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); + } else if (adreno_is_a8xx(adreno_gpu)) { + gmu_write(gmu, REG_A8XX_GPU_GMU_CX_GMU_CX_FALNEXT_INTF, 1); + gmu_write(gmu, REG_A8XX_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 + else if (!adreno_is_a8xx(adreno_gpu)) gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1); - if (state == GMU_WARM_BOOT) { - ret = a6xx_rpmh_start(gmu); - if (ret) - return ret; - } else { + ret = a6xx_rpmh_start(gmu); + if (ret) + return ret; + + if (state == GMU_COLD_BOOT) { if (WARN(!adreno_gpu->fw[ADRENO_FW_GMU], "GMU firmware is not loaded\n")) return -ENOENT; - ret = a6xx_rpmh_start(gmu); - if (ret) - return ret; - ret = a6xx_gmu_fw_load(gmu); if (ret) return ret; @@ -825,7 +938,10 @@ 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)) { + if (adreno_is_a8xx(adreno_gpu)) { + fence_range_upper = 0x32; + fence_range_lower = 0x8c0; + } else if (adreno_is_a7xx(adreno_gpu)) { fence_range_upper = 0x32; fence_range_lower = 0x8a0; } else { @@ -859,7 +975,12 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) chipid |= (adreno_gpu->chip_id << 8) & 0x0f00; /* patchid */ } - if (adreno_is_a7xx(adreno_gpu)) { + if (adreno_is_a8xx(adreno_gpu)) { + gmu_write(gmu, REG_A8XX_GMU_GENERAL_10, chipid); + gmu_write(gmu, REG_A8XX_GMU_GENERAL_8, + (gmu->log.iova & GENMASK(31, 12)) | + ((gmu->log.size / SZ_4K - 1) & GENMASK(7, 0))); + } else if (adreno_is_a7xx(adreno_gpu)) { gmu_write(gmu, REG_A7XX_GMU_GENERAL_10, chipid); gmu_write(gmu, REG_A7XX_GMU_GENERAL_8, (gmu->log.iova & GENMASK(31, 12)) | @@ -871,6 +992,15 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) gmu->log.iova | (gmu->log.size / SZ_4K - 1)); } + /* For A7x and newer, do the CX GBIF configurations before GMU wake up */ + for (int i = 0; (gbif_cx && gbif_cx[i].offset); i++) + gpu_write(gpu, gbif_cx[i].offset, gbif_cx[i].value); + + if (adreno_is_a8xx(adreno_gpu)) { + gpu_write(gpu, REG_A8XX_GBIF_CX_CONFIG, 0x20023000); + gmu_write(gmu, REG_A6XX_GMU_MRC_GBIF_QOS_CTRL, 0x33); + } + /* Set up the lowest idle level on the GMU */ a6xx_gmu_power_config(gmu); @@ -882,10 +1012,7 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) ret = a6xx_gmu_gfx_rail_on(gmu); if (ret) return ret; - } - /* Enable SPTP_PC if the CPU is responsible for it */ - if (gmu->idle_level < GMU_IDLE_STATE_SPTP) { ret = a6xx_sptprac_enable(gmu); if (ret) return ret; @@ -925,7 +1052,7 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu) u32 val, seqmem_off = 0; /* The second spin of A7xx GPUs messed with some register offsets.. */ - if (adreno_is_a740_family(adreno_gpu)) + if (adreno_is_a740_family(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) seqmem_off = 4; /* Make sure there are no outstanding RPMh votes */ @@ -937,6 +1064,22 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu) val, (val & 1), 100, 10000); gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off, val, (val & 1), 100, 1000); + + if (!adreno_is_a740_family(adreno_gpu) && !adreno_is_a8xx(adreno_gpu)) + return; + + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS4_DRV0_STATUS + seqmem_off, + val, (val & 1), 100, 10000); + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS5_DRV0_STATUS + seqmem_off, + val, (val & 1), 100, 10000); + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS6_DRV0_STATUS + seqmem_off, + val, (val & 1), 100, 10000); + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS7_DRV0_STATUS + seqmem_off, + val, (val & 1), 100, 1000); + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS8_DRV0_STATUS + seqmem_off, + val, (val & 1), 100, 10000); + gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS9_DRV0_STATUS + seqmem_off, + val, (val & 1), 100, 1000); } /* Force the GMU off in case it isn't responsive */ @@ -950,7 +1093,10 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu) * Turn off keep alive that might have been enabled by the hang * interrupt */ - gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 0); + if (adreno_is_a8xx(adreno_gpu)) + gmu_write(&a6xx_gpu->gmu, REG_A8XX_GMU_GMU_PWR_COL_KEEPALIVE, 0); + else + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 0); /* Flush all the queues */ a6xx_hfi_stop(gmu); @@ -976,10 +1122,12 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu) /* Halt the gmu cm3 core */ gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1); - a6xx_bus_clear_pending_transactions(adreno_gpu, true); + adreno_gpu->funcs->bus_halt(adreno_gpu, true); /* Reset GPU core blocks */ a6xx_gpu_sw_reset(gpu, true); + + a6xx_rpmh_stop(gmu); } static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu) @@ -1021,14 +1169,6 @@ 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); @@ -1051,6 +1191,9 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) return ret; } + /* Read the slice info on A8x GPUs */ + a8xx_gpu_get_slice_info(gpu); + /* Set the bus quota to a reasonable value for boot */ a6xx_gmu_set_initial_bw(gpu, gmu); @@ -1060,7 +1203,7 @@ 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 */ - if (adreno_is_a7xx(adreno_gpu)) { + if (adreno_is_a7xx(adreno_gpu) || adreno_is_a8xx(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) { @@ -1093,6 +1236,11 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) /* Set the GPU to the current freq */ a6xx_gmu_set_initial_freq(gpu, gmu); + if (refcount_read(&gpu->sysprof_active) > 1) { + ret = a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET); + if (!ret) + set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status); + } out: /* On failure, shut down the GMU to leave it in a good state */ if (ret) { @@ -1126,49 +1274,53 @@ static void a6xx_gmu_shutdown(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 val; + int ret; /* - * The GMU may still be in slumber unless the GPU started so check and - * skip putting it back into slumber if so + * GMU firmware's internal power state gets messed up if we send "prepare_slumber" hfi when + * oob_gpu handshake wasn't done after the last wake up. So do a dummy handshake here when + * required */ - val = gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE); + if (adreno_gpu->base.needs_hw_init) { + if (a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET)) + goto force_off; - if (val != 0xf) { - int ret = a6xx_gmu_wait_for_idle(gmu); + a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); + } - /* If the GMU isn't responding assume it is hung */ - if (ret) { - a6xx_gmu_force_off(gmu); - return; - } + if (test_and_clear_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status)) + a6xx_gmu_clear_oob(gmu, GMU_OOB_PERFCOUNTER_SET); - a6xx_bus_clear_pending_transactions(adreno_gpu, a6xx_gpu->hung); + ret = a6xx_gmu_wait_for_idle(gmu); - /* tell the GMU we want to slumber */ - ret = a6xx_gmu_notify_slumber(gmu); - if (ret) { - a6xx_gmu_force_off(gmu); - return; - } + /* If the GMU isn't responding assume it is hung */ + if (ret) + goto force_off; - ret = gmu_poll_timeout(gmu, - REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val, - !(val & A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS_GPUBUSYIGNAHB), - 100, 10000); + adreno_gpu->funcs->bus_halt(adreno_gpu, a6xx_gpu->hung); - /* - * Let the user know we failed to slumber but don't worry too - * much because we are powering down anyway - */ + /* tell the GMU we want to slumber */ + ret = a6xx_gmu_notify_slumber(gmu); + if (ret) + goto force_off; - if (ret) - DRM_DEV_ERROR(gmu->dev, - "Unable to slumber GMU: status = 0%x/0%x\n", - gmu_read(gmu, - REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS), - gmu_read(gmu, - REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2)); - } + ret = gmu_poll_timeout(gmu, + REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val, + !(val & A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS_GPUBUSYIGNAHB), + 100, 10000); + + /* + * Let the user know we failed to slumber but don't worry too + * much because we are powering down anyway + */ + + if (ret) + DRM_DEV_ERROR(gmu->dev, + "Unable to slumber GMU: status = 0%x/0%x\n", + gmu_read(gmu, + REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS), + gmu_read(gmu, + REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2)); /* Turn off HFI */ a6xx_hfi_stop(gmu); @@ -1178,6 +1330,11 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) /* Tell RPMh to power off the GPU */ a6xx_rpmh_stop(gmu); + + return; + +force_off: + a6xx_gmu_force_off(gmu); } @@ -1218,15 +1375,17 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu) static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu) { - msm_gem_kernel_put(gmu->hfi.obj, gmu->aspace); - msm_gem_kernel_put(gmu->debug.obj, gmu->aspace); - msm_gem_kernel_put(gmu->icache.obj, gmu->aspace); - msm_gem_kernel_put(gmu->dcache.obj, gmu->aspace); - msm_gem_kernel_put(gmu->dummy.obj, gmu->aspace); - msm_gem_kernel_put(gmu->log.obj, gmu->aspace); - - gmu->aspace->mmu->funcs->detach(gmu->aspace->mmu); - msm_gem_address_space_put(gmu->aspace); + struct msm_mmu *mmu = to_msm_vm(gmu->vm)->mmu; + + msm_gem_kernel_put(gmu->hfi.obj, gmu->vm); + msm_gem_kernel_put(gmu->debug.obj, gmu->vm); + msm_gem_kernel_put(gmu->icache.obj, gmu->vm); + msm_gem_kernel_put(gmu->dcache.obj, gmu->vm); + msm_gem_kernel_put(gmu->dummy.obj, gmu->vm); + msm_gem_kernel_put(gmu->log.obj, gmu->vm); + + mmu->funcs->detach(mmu); + drm_gpuvm_put(gmu->vm); } static int a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo, @@ -1255,7 +1414,7 @@ static int a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo, if (IS_ERR(bo->obj)) return PTR_ERR(bo->obj); - ret = msm_gem_get_and_pin_iova_range(bo->obj, gmu->aspace, &bo->iova, + ret = msm_gem_get_and_pin_iova_range(bo->obj, gmu->vm, &bo->iova, range_start, range_end); if (ret) { drm_gem_object_put(bo->obj); @@ -1265,24 +1424,120 @@ static int a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo, bo->virt = msm_gem_get_vaddr(bo->obj); bo->size = size; - msm_gem_object_set_name(bo->obj, name); + msm_gem_object_set_name(bo->obj, "%s", name); return 0; } -static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu) +static int a6xx_gmu_memory_probe(struct drm_device *drm, struct a6xx_gmu *gmu) { struct msm_mmu *mmu; mmu = msm_iommu_new(gmu->dev, 0); - if (!mmu) - return -ENODEV; if (IS_ERR(mmu)) return PTR_ERR(mmu); - gmu->aspace = msm_gem_address_space_create(mmu, "gmu", 0x0, 0x80000000); - if (IS_ERR(gmu->aspace)) - return PTR_ERR(gmu->aspace); + gmu->vm = msm_gem_vm_create(drm, mmu, "gmu", 0x0, 0x80000000, true); + if (IS_ERR(gmu->vm)) + return PTR_ERR(gmu->vm); + + return 0; +} + +/** + * struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager (BCM) + * @unit: divisor used to convert bytes/sec bw value to an RPMh msg + * @width: multiplier used to convert bytes/sec bw value to an RPMh msg + * @vcd: virtual clock domain that this bcm belongs to + * @reserved: reserved field + */ +struct bcm_db { + __le32 unit; + __le16 width; + u8 vcd; + u8 reserved; +}; + +static int a6xx_gmu_rpmh_bw_votes_init(struct adreno_gpu *adreno_gpu, + const struct a6xx_info *info, + struct a6xx_gmu *gmu) +{ + const struct bcm_db *bcm_data[GMU_MAX_BCMS] = { 0 }; + unsigned int bcm_index, bw_index, bcm_count = 0; + + /* Retrieve BCM data from cmd-db */ + for (bcm_index = 0; bcm_index < GMU_MAX_BCMS; bcm_index++) { + const struct a6xx_bcm *bcm = &info->bcms[bcm_index]; + size_t count; + + /* Stop at NULL terminated bcm entry */ + if (!bcm->name) + break; + + bcm_data[bcm_index] = cmd_db_read_aux_data(bcm->name, &count); + if (IS_ERR(bcm_data[bcm_index])) + return PTR_ERR(bcm_data[bcm_index]); + + if (!count) { + dev_err(gmu->dev, "invalid BCM '%s' aux data size\n", + bcm->name); + return -EINVAL; + } + + bcm_count++; + } + + /* Generate BCM votes values for each bandwidth & BCM */ + for (bw_index = 0; bw_index < gmu->nr_gpu_bws; bw_index++) { + u32 *data = gmu->gpu_ib_votes[bw_index]; + u32 bw = gmu->gpu_bw_table[bw_index]; + + /* Calculations loosely copied from bcm_aggregate() & tcs_cmd_gen() */ + for (bcm_index = 0; bcm_index < bcm_count; bcm_index++) { + const struct a6xx_bcm *bcm = &info->bcms[bcm_index]; + bool commit = false; + u64 peak; + u32 vote; + + if (bcm_index == bcm_count - 1 || + (bcm_data[bcm_index + 1] && + bcm_data[bcm_index]->vcd != bcm_data[bcm_index + 1]->vcd)) + commit = true; + + if (!bw) { + data[bcm_index] = BCM_TCS_CMD(commit, false, 0, 0); + continue; + } + + if (bcm->fixed) { + u32 perfmode = 0; + + /* GMU on A6xx votes perfmode on all valid bandwidth */ + if (!adreno_is_a7xx(adreno_gpu) || + (bcm->perfmode_bw && bw >= bcm->perfmode_bw)) + perfmode = bcm->perfmode; + + data[bcm_index] = BCM_TCS_CMD(commit, true, 0, perfmode); + continue; + } + + /* Multiply the bandwidth by the width of the connection */ + peak = (u64)bw * le16_to_cpu(bcm_data[bcm_index]->width); + do_div(peak, bcm->buswidth); + + /* Input bandwidth value is in KBps, scale the value to BCM unit */ + peak *= 1000; + do_div(peak, le32_to_cpu(bcm_data[bcm_index]->unit)); + + vote = clamp(peak, 1, BCM_TCS_CMD_VOTE_MASK); + + /* GMUs on A7xx votes on both x & y */ + if (adreno_is_a7xx(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) + data[bcm_index] = BCM_TCS_CMD(commit, true, vote, vote); + else + data[bcm_index] = BCM_TCS_CMD(commit, true, 0, vote); + } + } return 0; } @@ -1309,13 +1564,14 @@ static unsigned int a6xx_gmu_get_arc_level(struct device *dev, } static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes, - unsigned long *freqs, int freqs_count, const char *id) + unsigned long *freqs, int freqs_count, + const char *pri_id, const char *sec_id) { int i, j; const u16 *pri, *sec; size_t pri_count, sec_count; - pri = cmd_db_read_aux_data(id, &pri_count); + pri = cmd_db_read_aux_data(pri_id, &pri_count); if (IS_ERR(pri)) return PTR_ERR(pri); /* @@ -1326,13 +1582,7 @@ static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes, if (!pri_count) return -EINVAL; - /* - * Some targets have a separate gfx mxc rail. So try to read that first and then fall back - * to regular mx rail if it is missing - */ - sec = cmd_db_read_aux_data("gmxc.lvl", &sec_count); - if (IS_ERR(sec) && sec != ERR_PTR(-EPROBE_DEFER)) - sec = cmd_db_read_aux_data("mx.lvl", &sec_count); + sec = cmd_db_read_aux_data(sec_id, &sec_count); if (IS_ERR(sec)) return PTR_ERR(sec); @@ -1386,26 +1636,96 @@ static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes, return 0; } +static int a6xx_gmu_rpmh_dep_votes_init(struct device *dev, u32 *votes, + unsigned long *freqs, int freqs_count) +{ + const u16 *mx; + size_t count; + + mx = cmd_db_read_aux_data("mx.lvl", &count); + if (IS_ERR(mx)) + return PTR_ERR(mx); + /* + * The data comes back as an array of unsigned shorts so adjust the + * count accordingly + */ + count >>= 1; + if (!count) + return -EINVAL; + + /* Fix the vote for zero frequency */ + votes[0] = 0xffffffff; + + /* Construct a vote for rest of the corners */ + for (int i = 1; i < freqs_count; i++) { + unsigned int level = a6xx_gmu_get_arc_level(dev, freqs[i]); + u8 j, index = 0; + + /* Get the primary index that matches the arc level */ + for (j = 0; j < count; j++) { + if (mx[j] >= level) { + index = j; + break; + } + } + + if (j == count) { + DRM_DEV_ERROR(dev, + "Mx Level %u not found in the RPMh list\n", + level); + DRM_DEV_ERROR(dev, "Available levels:\n"); + for (j = 0; j < count; j++) + DRM_DEV_ERROR(dev, " %u\n", mx[j]); + + return -EINVAL; + } + + /* Construct the vote */ + votes[i] = (0x3fff << 14) | (index << 8) | (0xff); + } + + return 0; +} + /* * The GMU votes with the RPMh for itself and on behalf of the GPU but we need * to construct the list of votes on the CPU and send it over. Query the RPMh * voltage levels and build the votes + * The GMU can also vote for DDR interconnects, use the OPP bandwidth entries + * and BCM parameters to build the votes. */ static int a6xx_gmu_rpmh_votes_init(struct a6xx_gmu *gmu) { struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + const struct a6xx_info *info = adreno_gpu->info->a6xx; struct msm_gpu *gpu = &adreno_gpu->base; + const char *sec_id; + const u16 *gmxc; int ret; + gmxc = cmd_db_read_aux_data("gmxc.lvl", NULL); + if (gmxc == ERR_PTR(-EPROBE_DEFER)) + return -EPROBE_DEFER; + + /* If GMxC is present, prefer that as secondary rail for GX votes */ + sec_id = IS_ERR_OR_NULL(gmxc) ? "mx.lvl" : "gmxc.lvl"; + /* Build the GX votes */ ret = a6xx_gmu_rpmh_arc_votes_init(&gpu->pdev->dev, gmu->gx_arc_votes, - gmu->gpu_freqs, gmu->nr_gpu_freqs, "gfx.lvl"); + gmu->gpu_freqs, gmu->nr_gpu_freqs, "gfx.lvl", sec_id); /* Build the CX votes */ ret |= a6xx_gmu_rpmh_arc_votes_init(gmu->dev, gmu->cx_arc_votes, - gmu->gmu_freqs, gmu->nr_gmu_freqs, "cx.lvl"); + gmu->gmu_freqs, gmu->nr_gmu_freqs, "cx.lvl", "mx.lvl"); + + ret |= a6xx_gmu_rpmh_dep_votes_init(gmu->dev, gmu->dep_arc_votes, + gmu->gpu_freqs, gmu->nr_gpu_freqs); + + /* Build the interconnect votes */ + if (info->bcms && gmu->nr_gpu_bws > 1) + ret |= a6xx_gmu_rpmh_bw_votes_init(adreno_gpu, info, gmu); return ret; } @@ -1442,10 +1762,43 @@ static int a6xx_gmu_build_freq_table(struct device *dev, unsigned long *freqs, return index; } +static int a6xx_gmu_build_bw_table(struct device *dev, unsigned long *bandwidths, + u32 size) +{ + int count = dev_pm_opp_get_opp_count(dev); + struct dev_pm_opp *opp; + int i, index = 0; + unsigned int bandwidth = 1; + + /* + * The OPP table doesn't contain the "off" bandwidth level so we need to + * add 1 to the table size to account for it + */ + + if (WARN(count + 1 > size, + "The GMU bandwidth table is being truncated\n")) + count = size - 1; + + /* Set the "off" bandwidth */ + bandwidths[index++] = 0; + + for (i = 0; i < count; i++) { + opp = dev_pm_opp_find_bw_ceil(dev, &bandwidth, 0); + if (IS_ERR(opp)) + break; + + dev_pm_opp_put(opp); + bandwidths[index++] = bandwidth++; + } + + return index; +} + static int a6xx_gmu_pwrlevels_probe(struct a6xx_gmu *gmu) { struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + const struct a6xx_info *info = adreno_gpu->info->a6xx; struct msm_gpu *gpu = &adreno_gpu->base; int ret = 0; @@ -1472,10 +1825,88 @@ static int a6xx_gmu_pwrlevels_probe(struct a6xx_gmu *gmu) gmu->current_perf_index = gmu->nr_gpu_freqs - 1; + /* + * The GMU also handles GPU Interconnect Votes so build a list + * of DDR bandwidths from the GPU OPP table + */ + if (info->bcms) + gmu->nr_gpu_bws = a6xx_gmu_build_bw_table(&gpu->pdev->dev, + gmu->gpu_bw_table, ARRAY_SIZE(gmu->gpu_bw_table)); + /* Build the list of RPMh votes that we'll send to the GMU */ return a6xx_gmu_rpmh_votes_init(gmu); } +static int a6xx_gmu_acd_probe(struct a6xx_gmu *gmu) +{ + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct a6xx_hfi_acd_table *cmd = &gmu->acd_table; + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + struct msm_gpu *gpu = &adreno_gpu->base; + int ret, i, cmd_idx = 0; + extern bool disable_acd; + + /* Skip ACD probe if requested via module param */ + if (disable_acd) { + DRM_DEV_ERROR(gmu->dev, "Skipping GPU ACD probe\n"); + return 0; + } + + cmd->version = 1; + cmd->stride = 1; + cmd->enable_by_level = 0; + + /* Skip freq = 0 and parse acd-level for rest of the OPPs */ + for (i = 1; i < gmu->nr_gpu_freqs; i++) { + struct dev_pm_opp *opp; + struct device_node *np; + unsigned long freq; + u32 val; + + freq = gmu->gpu_freqs[i]; + /* This is unlikely to fail because we are passing back a known freq */ + opp = dev_pm_opp_find_freq_exact(&gpu->pdev->dev, freq, true); + np = dev_pm_opp_get_of_node(opp); + + ret = of_property_read_u32(np, "qcom,opp-acd-level", &val); + of_node_put(np); + dev_pm_opp_put(opp); + if (ret == -EINVAL) + continue; + else if (ret) { + DRM_DEV_ERROR(gmu->dev, "Unable to read acd level for freq %lu\n", freq); + return ret; + } + + cmd->enable_by_level |= BIT(i); + cmd->data[cmd_idx++] = val; + } + + cmd->num_levels = cmd_idx; + + /* It is a problem if qmp node is unavailable when ACD is required */ + if (cmd->enable_by_level && IS_ERR_OR_NULL(gmu->qmp)) { + DRM_DEV_ERROR(gmu->dev, "Unable to send ACD state to AOSS\n"); + return -EINVAL; + } + + /* Otherwise, nothing to do if qmp is unavailable */ + if (IS_ERR_OR_NULL(gmu->qmp)) + return 0; + + /* + * Notify AOSS about the ACD state. AOSS is supposed to assume that ACD is disabled on + * system reset. So it is harmless if we couldn't notify 'OFF' state + */ + ret = qmp_send(gmu->qmp, "{class: gpu, res: acd, val: %d}", !!cmd->enable_by_level); + if (ret && cmd->enable_by_level) { + DRM_DEV_ERROR(gmu->dev, "Failed to send ACD state to AOSS\n"); + return ret; + } + + return 0; +} + static int a6xx_gmu_clocks_probe(struct a6xx_gmu *gmu) { int ret = devm_clk_bulk_get_all(gmu->dev, &gmu->clocks); @@ -1494,27 +1925,6 @@ static int a6xx_gmu_clocks_probe(struct a6xx_gmu *gmu) return 0; } -static void __iomem *a6xx_gmu_get_mmio(struct platform_device *pdev, - const char *name) -{ - void __iomem *ret; - struct resource *res = platform_get_resource_byname(pdev, - IORESOURCE_MEM, name); - - if (!res) { - DRM_DEV_ERROR(&pdev->dev, "Unable to find the %s registers\n", name); - return ERR_PTR(-EINVAL); - } - - ret = ioremap(res->start, resource_size(res)); - if (!ret) { - DRM_DEV_ERROR(&pdev->dev, "Unable to map the %s registers\n", name); - return ERR_PTR(-EINVAL); - } - - return ret; -} - static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev, const char *name, irq_handler_t handler) { @@ -1532,11 +1942,39 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev, return irq; } +void a6xx_gmu_sysprof_setup(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; + unsigned int sysprof_active; + + /* Nothing to do if GPU is suspended. We will handle this during GMU resume */ + if (!pm_runtime_get_if_active(&gpu->pdev->dev)) + return; + + mutex_lock(&gmu->lock); + + sysprof_active = refcount_read(&gpu->sysprof_active); + + /* + * 'Perfcounter select' register values are lost during IFPC collapse. To avoid that, + * use the currently unused perfcounter oob vote to block IFPC when sysprof is active + */ + if ((sysprof_active > 1) && !test_and_set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status)) + a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET); + else if ((sysprof_active == 1) && test_and_clear_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status)) + a6xx_gmu_clear_oob(gmu, GMU_OOB_PERFCOUNTER_SET); + + mutex_unlock(&gmu->lock); + + pm_runtime_put(&gpu->pdev->dev); +} + void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) { struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; struct a6xx_gmu *gmu = &a6xx_gpu->gmu; - struct platform_device *pdev = to_platform_device(gmu->dev); mutex_lock(&gmu->lock); if (!gmu->initialized) { @@ -1565,12 +2003,11 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) qmp_put(gmu->qmp); iounmap(gmu->mmio); - if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "rscc")) - iounmap(gmu->rscc); gmu->mmio = NULL; gmu->rscc = NULL; - if (!adreno_has_gmu_wrapper(adreno_gpu)) { + if (!adreno_has_gmu_wrapper(adreno_gpu) && + !adreno_has_rgmu(adreno_gpu)) { a6xx_gmu_memory_free(gmu); free_irq(gmu->gmu_irq, gmu); @@ -1592,10 +2029,38 @@ static int cxpd_notifier_cb(struct notifier_block *nb, return 0; } +static void __iomem *a6xx_gmu_get_mmio(struct platform_device *pdev, + const char *name, resource_size_t *start) +{ + void __iomem *ret; + struct resource *res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, name); + + if (!res) { + DRM_DEV_ERROR(&pdev->dev, "Unable to find the %s registers\n", name); + return ERR_PTR(-EINVAL); + } + + ret = ioremap(res->start, resource_size(res)); + if (!ret) { + DRM_DEV_ERROR(&pdev->dev, "Unable to map the %s registers\n", name); + return ERR_PTR(-EINVAL); + } + + if (start) + *start = res->start; + + return ret; +} + int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) { struct platform_device *pdev = of_find_device_by_node(node); + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + struct msm_gpu *gpu = &adreno_gpu->base; struct a6xx_gmu *gmu = &a6xx_gpu->gmu; + resource_size_t start; + struct resource *res; int ret; if (!pdev) @@ -1603,20 +2068,38 @@ int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) gmu->dev = &pdev->dev; - of_dma_configure(gmu->dev, node, true); + ret = of_dma_configure(gmu->dev, node, true); + if (ret) + return ret; pm_runtime_enable(gmu->dev); /* Mark legacy for manual SPTPRAC control */ gmu->legacy = true; + /* RGMU requires clocks */ + ret = devm_clk_bulk_get_all(gmu->dev, &gmu->clocks); + if (ret < 0) + goto err_clk; + + gmu->nr_clocks = ret; + /* Map the GMU registers */ - gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu"); + gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu", &start); if (IS_ERR(gmu->mmio)) { ret = PTR_ERR(gmu->mmio); goto err_mmio; } + res = platform_get_resource_byname(gpu->pdev, IORESOURCE_MEM, "kgsl_3d0_reg_memory"); + if (!res) { + ret = -EINVAL; + goto err_mmio; + } + + /* Identify gmu base offset from gpu base address */ + gmu->mmio_offset = (u32)(start - res->start); + gmu->cxpd = dev_pm_domain_attach_by_name(gmu->dev, "cx"); if (IS_ERR(gmu->cxpd)) { ret = PTR_ERR(gmu->cxpd); @@ -1649,6 +2132,7 @@ detach_cxpd: err_mmio: iounmap(gmu->mmio); +err_clk: /* Drop reference taken in of_find_device_by_node */ put_device(gmu->dev); @@ -1657,10 +2141,13 @@ err_mmio: int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) { + struct platform_device *pdev = of_find_device_by_node(node); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + struct msm_gpu *gpu = &adreno_gpu->base; struct a6xx_gmu *gmu = &a6xx_gpu->gmu; - struct platform_device *pdev = of_find_device_by_node(node); struct device_link *link; + resource_size_t start; + struct resource *res; int ret; if (!pdev) @@ -1668,10 +2155,13 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) gmu->dev = &pdev->dev; - of_dma_configure(gmu->dev, node, true); + ret = of_dma_configure(gmu->dev, node, true); + if (ret) + return ret; - /* Fow now, don't do anything fancy until we get our feet under us */ - gmu->idle_level = GMU_IDLE_STATE_ACTIVE; + /* Set GMU idle level */ + gmu->idle_level = (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) ? + GMU_IDLE_STATE_IFPC : GMU_IDLE_STATE_ACTIVE; pm_runtime_enable(gmu->dev); @@ -1680,7 +2170,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) if (ret) goto err_put_device; - ret = a6xx_gmu_memory_probe(gmu); + ret = a6xx_gmu_memory_probe(adreno_gpu->base.dev, gmu); if (ret) goto err_put_device; @@ -1693,13 +2183,14 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) */ gmu->dummy.size = SZ_4K; if (adreno_is_a660_family(adreno_gpu) || - adreno_is_a7xx(adreno_gpu)) { + adreno_is_a7xx(adreno_gpu) || + adreno_is_a8xx(adreno_gpu)) { ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_4K * 7, 0x60400000, "debug"); if (ret) goto err_memory; - gmu->dummy.size = SZ_8K; + gmu->dummy.size = SZ_16K; } /* Allocate memory for the GMU dummy page */ @@ -1710,7 +2201,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) /* Note that a650 family also includes a660 family: */ if (adreno_is_a650_family(adreno_gpu) || - adreno_is_a7xx(adreno_gpu)) { + adreno_is_a7xx(adreno_gpu) || + adreno_is_a8xx(adreno_gpu)) { ret = a6xx_gmu_memory_alloc(gmu, &gmu->icache, SZ_16M - SZ_16K, 0x04000, "icache"); if (ret) @@ -1752,19 +2244,30 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) goto err_memory; /* Map the GMU registers */ - gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu"); + gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu", &start); if (IS_ERR(gmu->mmio)) { ret = PTR_ERR(gmu->mmio); goto err_memory; } + res = platform_get_resource_byname(gpu->pdev, IORESOURCE_MEM, "kgsl_3d0_reg_memory"); + if (!res) { + ret = -EINVAL; + goto err_mmio; + } + + /* Identify gmu base offset from gpu base address */ + gmu->mmio_offset = (u32)(start - res->start); + if (adreno_is_a650_family(adreno_gpu) || adreno_is_a7xx(adreno_gpu)) { - gmu->rscc = a6xx_gmu_get_mmio(pdev, "rscc"); + gmu->rscc = devm_platform_ioremap_resource_byname(pdev, "rscc"); if (IS_ERR(gmu->rscc)) { ret = -ENODEV; goto err_mmio; } + } else if (adreno_is_a8xx(adreno_gpu)) { + gmu->rscc = gmu->mmio + 0x19000; } else { gmu->rscc = gmu->mmio + 0x23000; } @@ -1790,10 +2293,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) goto detach_cxpd; } + /* Other errors are handled during GPU ACD probe */ 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; + if (PTR_ERR_OR_ZERO(gmu->qmp) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto detach_gxpd; } init_completion(&gmu->pd_gate); @@ -1809,6 +2313,10 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) /* Get the power levels for the GMU and GPU */ a6xx_gmu_pwrlevels_probe(gmu); + ret = a6xx_gmu_acd_probe(gmu); + if (ret) + goto detach_gxpd; + /* Set up the HFI queues */ a6xx_hfi_init(gmu); @@ -1819,7 +2327,13 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) return 0; -remove_device_link: +detach_gxpd: + if (!IS_ERR_OR_NULL(gmu->gxpd)) + dev_pm_domain_detach(gmu->gxpd, false); + + if (!IS_ERR_OR_NULL(gmu->qmp)) + qmp_put(gmu->qmp); + device_link_del(link); detach_cxpd: @@ -1827,8 +2341,6 @@ detach_cxpd: err_mmio: iounmap(gmu->mmio); - if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "rscc")) - iounmap(gmu->rscc); free_irq(gmu->gmu_irq, gmu); free_irq(gmu->hfi_irq, gmu); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index b4a79f88ccf4..2af074c8e8cf 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -19,6 +19,18 @@ struct a6xx_gmu_bo { u64 iova; }; +#define GMU_MAX_GX_FREQS 32 +#define GMU_MAX_CX_FREQS 6 +#define GMU_MAX_BCMS 3 + +struct a6xx_bcm { + char *name; + unsigned int buswidth; + bool fixed; + unsigned int perfmode; + unsigned int perfmode_bw; +}; + /* * These define the different GMU wake up options - these define how both the * CPU and the GMU bring up the hardware @@ -38,6 +50,9 @@ struct a6xx_gmu_bo { /* The GMU does not do any idle state management */ #define GMU_IDLE_STATE_ACTIVE 0 +/* Unknown power state. Not exposed by the firmware. For documentation purpose only */ +#define GMU_IDLE_STATE_RESERVED 1 + /* The GMU manages SPTP power collapse */ #define GMU_IDLE_STATE_SPTP 2 @@ -50,9 +65,10 @@ struct a6xx_gmu { /* For serializing communication with the GMU: */ struct mutex lock; - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; void __iomem *mmio; + u32 mmio_offset; void __iomem *rscc; int hfi_irq; @@ -79,12 +95,18 @@ struct a6xx_gmu { int current_perf_index; int nr_gpu_freqs; - unsigned long gpu_freqs[16]; - u32 gx_arc_votes[16]; + unsigned long gpu_freqs[GMU_MAX_GX_FREQS]; + u32 gx_arc_votes[GMU_MAX_GX_FREQS]; + u32 dep_arc_votes[GMU_MAX_GX_FREQS]; + struct a6xx_hfi_acd_table acd_table; + + int nr_gpu_bws; + unsigned long gpu_bw_table[GMU_MAX_GX_FREQS]; + u32 gpu_ib_votes[GMU_MAX_GX_FREQS][GMU_MAX_BCMS]; int nr_gmu_freqs; - unsigned long gmu_freqs[4]; - u32 cx_arc_votes[4]; + unsigned long gmu_freqs[GMU_MAX_CX_FREQS]; + u32 cx_arc_votes[GMU_MAX_CX_FREQS]; unsigned long freq; @@ -100,22 +122,33 @@ struct a6xx_gmu { struct qmp *qmp; struct a6xx_hfi_msg_bw_table *bw_table; + +/* To check if we can trigger sleep seq at PDC. Cleared in a6xx_rpmh_stop() */ +#define GMU_STATUS_FW_START 0 +/* To track if PDC sleep seq was done */ +#define GMU_STATUS_PDC_SLEEP 1 +/* To track Perfcounter OOB set status */ +#define GMU_STATUS_OOB_PERF_SET 2 + unsigned long status; }; +#define GMU_BYTE_OFFSET(gmu, offset) (((offset) << 2) - (gmu)->mmio_offset) + static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset) { - return readl(gmu->mmio + (offset << 2)); + /* The 'offset' is based on GPU's start address. Adjust it */ + return readl(gmu->mmio + GMU_BYTE_OFFSET(gmu, offset)); } static inline void gmu_write(struct a6xx_gmu *gmu, u32 offset, u32 value) { - writel(value, gmu->mmio + (offset << 2)); + writel(value, gmu->mmio + GMU_BYTE_OFFSET(gmu, offset)); } static inline void gmu_write_bulk(struct a6xx_gmu *gmu, u32 offset, const u32 *data, u32 size) { - memcpy_toio(gmu->mmio + (offset << 2), data, size); + memcpy_toio(gmu->mmio + GMU_BYTE_OFFSET(gmu, offset), data, size); wmb(); } @@ -132,14 +165,17 @@ static inline u64 gmu_read64(struct a6xx_gmu *gmu, u32 lo, u32 hi) { u64 val; - val = (u64) readl(gmu->mmio + (lo << 2)); - val |= ((u64) readl(gmu->mmio + (hi << 2)) << 32); + val = gmu_read(gmu, lo); + val |= ((u64) gmu_read(gmu, hi) << 32); return val; } #define gmu_poll_timeout(gmu, addr, val, cond, interval, timeout) \ - readl_poll_timeout((gmu)->mmio + ((addr) << 2), val, cond, \ + readl_poll_timeout((gmu)->mmio + (GMU_BYTE_OFFSET(gmu, addr)), val, \ + cond, interval, timeout) +#define gmu_poll_timeout_atomic(gmu, addr, val, cond, interval, timeout) \ + readl_poll_timeout_atomic((gmu)->mmio + (GMU_BYTE_OFFSET(gmu, addr)), val, cond, \ interval, timeout) static inline u32 gmu_read_rscc(struct a6xx_gmu *gmu, u32 offset) @@ -193,7 +229,7 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu); int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state); void a6xx_hfi_stop(struct a6xx_gmu *gmu); int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu); -int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index); +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, u32 perf_index, u32 bw_index); bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu); bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 019610341df1..0200a7e71cdf 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -16,6 +16,97 @@ #define GPU_PAS_ID 13 +static u64 read_gmu_ao_counter(struct a6xx_gpu *a6xx_gpu) +{ + u64 count_hi, count_lo, temp; + + do { + count_hi = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H); + count_lo = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_L); + temp = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H); + } while (unlikely(count_hi != temp)); + + return (count_hi << 32) | count_lo; +} + +static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask) +{ + /* Success if !writedropped0/1 */ + if (!(status & mask)) + return true; + + udelay(10); + + /* Try to update fenced register again */ + gpu_write(gpu, offset, value); + + /* We can't do a posted write here because the power domain could be + * in collapse state. So use the heaviest barrier instead + */ + mb(); + return false; +} + +static int fenced_write(struct a6xx_gpu *a6xx_gpu, u32 offset, u32 value, u32 mask) +{ + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + struct msm_gpu *gpu = &adreno_gpu->base; + struct a6xx_gmu *gmu = &a6xx_gpu->gmu; + u32 status; + + gpu_write(gpu, offset, value); + + /* Nothing else to be done in the case of no-GMU */ + if (adreno_has_gmu_wrapper(adreno_gpu)) + return 0; + + /* We can't do a posted write here because the power domain could be + * in collapse state. So use the heaviest barrier instead + */ + mb(); + + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status, + fence_status_check(gpu, offset, value, status, mask), 0, 1000)) + return 0; + + /* Try again for another 1ms before failing */ + gpu_write(gpu, offset, value); + mb(); + + if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status, + fence_status_check(gpu, offset, value, status, mask), 0, 1000)) { + /* + * The 'delay' warning is here because the pause to print this + * warning will allow gpu to move to power collapse which + * defeats the purpose of continuous polling for 2 ms + */ + dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n", + offset); + return 0; + } + + dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n", + offset); + + return -ETIMEDOUT; +} + +int a6xx_fenced_write(struct a6xx_gpu *a6xx_gpu, u32 offset, u64 value, u32 mask, bool is_64b) +{ + int ret; + + ret = fenced_write(a6xx_gpu, offset, lower_32_bits(value), mask); + if (ret) + return ret; + + if (!is_64b) + return 0; + + ret = fenced_write(a6xx_gpu, offset + 1, upper_32_bits(value), mask); + + return ret; +} + static inline bool _a6xx_check_idle(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); @@ -66,7 +157,7 @@ static void update_shadow_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) } } -static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); @@ -86,7 +177,7 @@ static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) /* Update HW if this is the current ring and we are not in preempt*/ if (!a6xx_in_preempt(a6xx_gpu)) { if (a6xx_gpu->cur_ring == ring) - gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr); + a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false); else ring->restore_wptr = true; } else { @@ -111,7 +202,8 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, struct msm_ringbuffer *ring, struct msm_gem_submit *submit) { bool sysprof = refcount_read(&a6xx_gpu->base.base.sysprof_active) > 1; - struct msm_file_private *ctx = submit->queue->ctx; + struct msm_context *ctx = submit->queue->ctx; + struct drm_gpuvm *vm = msm_context_vm(submit->dev, ctx); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; phys_addr_t ttbr; u32 asid; @@ -120,7 +212,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, if (ctx->seqno == ring->cur_ctx_seqno) return; - if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid)) + if (msm_iommu_pagetable_params(to_msm_vm(vm)->mmu, &ttbr, &asid)) return; if (adreno_gpu->info->family >= ADRENO_7XX_GEN1) { @@ -130,17 +222,44 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence))); OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence))); OUT_RING(ring, submit->seqno - 1); + + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BOTH); + + /* Reset state used to synchronize BR and BV */ + OUT_PKT7(ring, CP_RESET_CONTEXT_STATE, 1); + OUT_RING(ring, + CP_RESET_CONTEXT_STATE_0_CLEAR_ON_CHIP_TS | + CP_RESET_CONTEXT_STATE_0_CLEAR_RESOURCE_TABLE | + CP_RESET_CONTEXT_STATE_0_CLEAR_BV_BR_COUNTER | + CP_RESET_CONTEXT_STATE_0_RESET_GLOBAL_LOCAL_TS); + + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BOTH); + + OUT_PKT7(ring, CP_EVENT_WRITE, 1); + OUT_RING(ring, LRZ_FLUSH_INVALIDATE); + + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BR); } if (!sysprof) { - if (!adreno_is_a7xx(adreno_gpu)) { + if (!(adreno_is_a7xx(adreno_gpu) || adreno_is_a8xx(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); + if (adreno_is_a8xx(adreno_gpu)) { + OUT_PKT4(ring, REG_A8XX_RBBM_PERFCTR_SRAM_INIT_CMD, 1); + OUT_RING(ring, 1); + OUT_PKT4(ring, REG_A8XX_RBBM_SLICE_PERFCTR_SRAM_INIT_CMD, 1); + OUT_RING(ring, 1); + } else { + OUT_PKT4(ring, REG_A6XX_RBBM_PERFCTR_SRAM_INIT_CMD, 1); + OUT_RING(ring, 1); + } } /* Execute the table update */ @@ -158,8 +277,8 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, * Needed for preemption */ OUT_PKT7(ring, CP_MEM_WRITE, 5); - OUT_RING(ring, CP_MEM_WRITE_0_ADDR_LO(lower_32_bits(memptr))); - OUT_RING(ring, CP_MEM_WRITE_1_ADDR_HI(upper_32_bits(memptr))); + OUT_RING(ring, A5XX_CP_MEM_WRITE_ADDR_LO(lower_32_bits(memptr))); + OUT_RING(ring, A5XX_CP_MEM_WRITE_ADDR_HI(upper_32_bits(memptr))); OUT_RING(ring, lower_32_bits(ttbr)); OUT_RING(ring, upper_32_bits(ttbr)); OUT_RING(ring, ctx->seqno); @@ -169,7 +288,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, * to make sure BV doesn't race ahead while BR is still switching * pagetables. */ - if (adreno_is_a7xx(&a6xx_gpu->base)) { + if (adreno_is_a7xx(&a6xx_gpu->base) || adreno_is_a8xx(&a6xx_gpu->base)) { OUT_PKT7(ring, CP_THREAD_CONTROL, 1); OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BR); } @@ -183,20 +302,22 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, OUT_RING(ring, CACHE_INVALIDATE); if (!sysprof) { + u32 reg_status = adreno_is_a8xx(adreno_gpu) ? + REG_A8XX_RBBM_PERFCTR_SRAM_INIT_STATUS : + REG_A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS; /* * Wait for SRAM clear after the pgtable update, so the * two can happen in parallel: */ OUT_PKT7(ring, CP_WAIT_REG_MEM, 6); OUT_RING(ring, CP_WAIT_REG_MEM_0_FUNCTION(WRITE_EQ)); - OUT_RING(ring, CP_WAIT_REG_MEM_1_POLL_ADDR_LO( - REG_A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS)); - OUT_RING(ring, CP_WAIT_REG_MEM_2_POLL_ADDR_HI(0)); + OUT_RING(ring, CP_WAIT_REG_MEM_POLL_ADDR_LO(reg_status)); + OUT_RING(ring, CP_WAIT_REG_MEM_POLL_ADDR_HI(0)); OUT_RING(ring, CP_WAIT_REG_MEM_3_REF(0x1)); OUT_RING(ring, CP_WAIT_REG_MEM_4_MASK(0x1)); OUT_RING(ring, CP_WAIT_REG_MEM_5_DELAY_LOOP_CYCLES(0)); - if (!adreno_is_a7xx(adreno_gpu)) { + if (!(adreno_is_a7xx(adreno_gpu) || adreno_is_a8xx(adreno_gpu))) { /* Re-enable protected mode: */ OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); OUT_RING(ring, 1); @@ -212,6 +333,8 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) struct msm_ringbuffer *ring = submit->ring; unsigned int i, ibs = 0; + adreno_check_and_reenable_stall(adreno_gpu); + a6xx_set_pagetable(a6xx_gpu, ring, submit); get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0), @@ -242,10 +365,10 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) break; fallthrough; case MSM_SUBMIT_CMD_BUF: - OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3); + OUT_PKT7(ring, CP_INDIRECT_BUFFER, 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); + OUT_RING(ring, A5XX_CP_INDIRECT_BUFFER_2_IB_SIZE(submit->cmd[i].size)); ibs++; break; } @@ -267,7 +390,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) rbmemptr_stats(ring, index, alwayson_end)); /* Write the fence to the scratch register */ - OUT_PKT4(ring, REG_A6XX_CP_SCRATCH_REG(2), 1); + OUT_PKT4(ring, REG_A6XX_CP_SCRATCH(2), 1); OUT_RING(ring, submit->seqno); /* @@ -281,8 +404,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence))); OUT_RING(ring, submit->seqno); - trace_msm_gpu_submit_flush(submit, - gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER)); + trace_msm_gpu_submit_flush(submit, read_gmu_ao_counter(a6xx_gpu)); a6xx_flush(gpu, ring); } @@ -333,8 +455,11 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) 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; + u32 rbbm_perfctr_cp0, cp_always_on_counter; unsigned int i, ibs = 0; + adreno_check_and_reenable_stall(adreno_gpu); + /* * Toggle concurrent binning for pagetable switch and set the thread to * BR since only it can execute the pagetable switch packets. @@ -351,10 +476,16 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) if (gpu->nr_rings > 1) a6xx_emit_set_pseudo_reg(ring, a6xx_gpu, submit->queue); - get_stats_counter(ring, REG_A7XX_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)); + if (adreno_is_a8xx(adreno_gpu)) { + rbbm_perfctr_cp0 = REG_A8XX_RBBM_PERFCTR_CP(0); + cp_always_on_counter = REG_A8XX_CP_ALWAYS_ON_COUNTER; + } else { + rbbm_perfctr_cp0 = REG_A7XX_RBBM_PERFCTR_CP(0); + cp_always_on_counter = REG_A6XX_CP_ALWAYS_ON_COUNTER; + } + + get_stats_counter(ring, rbbm_perfctr_cp0, rbmemptr_stats(ring, index, cpcycles_start)); + get_stats_counter(ring, cp_always_on_counter, rbmemptr_stats(ring, index, alwayson_start)); OUT_PKT7(ring, CP_THREAD_CONTROL, 1); OUT_RING(ring, CP_SET_THREAD_BOTH); @@ -377,10 +508,10 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) break; fallthrough; case MSM_SUBMIT_CMD_BUF: - OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3); + OUT_PKT7(ring, CP_INDIRECT_BUFFER, 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); + OUT_RING(ring, A5XX_CP_INDIRECT_BUFFER_2_IB_SIZE(submit->cmd[i].size)); ibs++; break; } @@ -401,14 +532,17 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) OUT_RING(ring, 0x00e); /* IB1LIST end */ } - get_stats_counter(ring, REG_A7XX_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)); + get_stats_counter(ring, rbbm_perfctr_cp0, rbmemptr_stats(ring, index, cpcycles_end)); + get_stats_counter(ring, 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); + if (adreno_is_a8xx(adreno_gpu)) { + OUT_PKT4(ring, REG_A8XX_CP_SCRATCH_GLOBAL(2), 1); + OUT_RING(ring, submit->seqno); + } else { + OUT_PKT4(ring, REG_A6XX_CP_SCRATCH(2), 1); + OUT_RING(ring, submit->seqno); + } OUT_PKT7(ring, CP_THREAD_CONTROL, 1); OUT_RING(ring, CP_SET_THREAD_BR); @@ -480,8 +614,7 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) } - trace_msm_gpu_submit_flush(submit, - gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER)); + trace_msm_gpu_submit_flush(submit, read_gmu_ao_counter(a6xx_gpu)); a6xx_flush(gpu, ring); @@ -504,15 +637,26 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state) if (adreno_is_a630(adreno_gpu)) clock_cntl_on = 0x8aa8aa02; - else if (adreno_is_a610(adreno_gpu)) + else if (adreno_is_a610(adreno_gpu) || adreno_is_a612(adreno_gpu)) clock_cntl_on = 0xaaa8aa82; else if (adreno_is_a702(adreno_gpu)) clock_cntl_on = 0xaaaaaa82; else clock_cntl_on = 0x8aa8aa82; - cgc_delay = adreno_is_a615_family(adreno_gpu) ? 0x111 : 0x10111; - cgc_hyst = adreno_is_a615_family(adreno_gpu) ? 0x555 : 0x5555; + if (adreno_is_a612(adreno_gpu)) + cgc_delay = 0x11; + else if (adreno_is_a615_family(adreno_gpu)) + cgc_delay = 0x111; + else + cgc_delay = 0x10111; + + if (adreno_is_a612(adreno_gpu)) + cgc_hyst = 0x55; + else if (adreno_is_a615_family(adreno_gpu)) + cgc_hyst = 0x555; + else + cgc_hyst = 0x5555; gmu_write(&a6xx_gpu->gmu, REG_A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL, state ? adreno_gpu->info->a6xx->gmu_cgc_mode : 0); @@ -585,110 +729,124 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu) gpu_write(gpu, REG_A6XX_CP_PROTECT(protect->count_max - 1), protect->regs[i]); } -static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu) +static int a6xx_calc_ubwc_config(struct adreno_gpu *gpu) { - gpu->ubwc_config.rgb565_predicator = 0; - gpu->ubwc_config.uavflagprd_inv = 0; - gpu->ubwc_config.min_acc_len = 0; - gpu->ubwc_config.ubwc_swizzle = 0x6; - gpu->ubwc_config.macrotile_mode = 0; - gpu->ubwc_config.highest_bank_bit = 15; + const struct qcom_ubwc_cfg_data *common_cfg; + struct qcom_ubwc_cfg_data *cfg = &gpu->_ubwc_config; + + /* Inherit the common config and make some necessary fixups */ + common_cfg = qcom_ubwc_config_get_data(); + if (IS_ERR(common_cfg)) + return PTR_ERR(common_cfg); + + /* Copy the data into the internal struct to drop the const qualifier (temporarily) */ + *cfg = *common_cfg; + + /* Use common config as is for A8x */ + if (!adreno_is_a8xx(gpu)) { + cfg->ubwc_swizzle = 0x6; + cfg->highest_bank_bit = 15; + } if (adreno_is_a610(gpu)) { - gpu->ubwc_config.highest_bank_bit = 13; - gpu->ubwc_config.min_acc_len = 1; - gpu->ubwc_config.ubwc_swizzle = 0x7; + cfg->highest_bank_bit = 13; + cfg->ubwc_swizzle = 0x7; } + if (adreno_is_a612(gpu)) + cfg->highest_bank_bit = 14; + if (adreno_is_a618(gpu)) - gpu->ubwc_config.highest_bank_bit = 14; + cfg->highest_bank_bit = 14; if (adreno_is_a619(gpu)) /* TODO: Should be 14 but causes corruption at e.g. 1920x1200 on DP */ - gpu->ubwc_config.highest_bank_bit = 13; + cfg->highest_bank_bit = 13; if (adreno_is_a619_holi(gpu)) - gpu->ubwc_config.highest_bank_bit = 13; + cfg->highest_bank_bit = 13; - if (adreno_is_a621(gpu)) { - gpu->ubwc_config.highest_bank_bit = 13; - gpu->ubwc_config.amsbc = 1; - gpu->ubwc_config.uavflagprd_inv = 2; - } - - if (adreno_is_a640_family(gpu)) - gpu->ubwc_config.amsbc = 1; + if (adreno_is_a621(gpu)) + cfg->highest_bank_bit = 13; - if (adreno_is_a680(gpu)) - gpu->ubwc_config.macrotile_mode = 1; + if (adreno_is_a623(gpu)) + cfg->highest_bank_bit = 16; if (adreno_is_a650(gpu) || adreno_is_a660(gpu) || adreno_is_a690(gpu) || adreno_is_a730(gpu) || adreno_is_a740_family(gpu)) { - /* TODO: get ddr type from bootloader and use 2 for LPDDR4 */ - gpu->ubwc_config.highest_bank_bit = 16; - gpu->ubwc_config.amsbc = 1; - gpu->ubwc_config.rgb565_predicator = 1; - gpu->ubwc_config.uavflagprd_inv = 2; - gpu->ubwc_config.macrotile_mode = 1; + /* TODO: get ddr type from bootloader and use 15 for LPDDR4 */ + cfg->highest_bank_bit = 16; } if (adreno_is_a663(gpu)) { - gpu->ubwc_config.highest_bank_bit = 13; - gpu->ubwc_config.amsbc = 1; - gpu->ubwc_config.rgb565_predicator = 1; - gpu->ubwc_config.uavflagprd_inv = 2; - gpu->ubwc_config.macrotile_mode = 1; - gpu->ubwc_config.ubwc_swizzle = 0x4; + cfg->highest_bank_bit = 13; + cfg->ubwc_swizzle = 0x4; } - if (adreno_is_7c3(gpu)) { - gpu->ubwc_config.highest_bank_bit = 14; - gpu->ubwc_config.amsbc = 1; - gpu->ubwc_config.rgb565_predicator = 1; - gpu->ubwc_config.uavflagprd_inv = 2; - gpu->ubwc_config.macrotile_mode = 1; - } + if (adreno_is_7c3(gpu)) + cfg->highest_bank_bit = 14; - if (adreno_is_a702(gpu)) { - gpu->ubwc_config.highest_bank_bit = 14; - gpu->ubwc_config.min_acc_len = 1; - } + if (adreno_is_a702(gpu)) + cfg->highest_bank_bit = 14; + + if (cfg->highest_bank_bit != common_cfg->highest_bank_bit) + DRM_WARN_ONCE("Inconclusive highest_bank_bit value: %u (GPU) vs %u (UBWC_CFG)\n", + cfg->highest_bank_bit, common_cfg->highest_bank_bit); + + if (cfg->ubwc_swizzle != common_cfg->ubwc_swizzle) + DRM_WARN_ONCE("Inconclusive ubwc_swizzle value: %u (GPU) vs %u (UBWC_CFG)\n", + cfg->ubwc_swizzle, common_cfg->ubwc_swizzle); + + gpu->ubwc_config = &gpu->_ubwc_config; + + return 0; } static void a6xx_set_ubwc_config(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + const struct qcom_ubwc_cfg_data *cfg = adreno_gpu->ubwc_config; /* * We subtract 13 from the highest bank bit (13 is the minimum value * allowed by hw) and write the lowest two bits of the remaining value * as hbb_lo and the one above it as hbb_hi to the hardware. */ - BUG_ON(adreno_gpu->ubwc_config.highest_bank_bit < 13); - u32 hbb = adreno_gpu->ubwc_config.highest_bank_bit - 13; + BUG_ON(cfg->highest_bank_bit < 13); + u32 hbb = cfg->highest_bank_bit - 13; + bool rgb565_predicator = cfg->ubwc_enc_version >= UBWC_4_0; + u32 level2_swizzling_dis = !(cfg->ubwc_swizzle & UBWC_SWIZZLE_ENABLE_LVL2); + bool ubwc_mode = qcom_ubwc_get_ubwc_mode(cfg); + bool amsbc = cfg->ubwc_enc_version >= UBWC_3_0; + bool min_acc_len_64b = false; + u8 uavflagprd_inv = 0; u32 hbb_hi = hbb >> 2; u32 hbb_lo = hbb & 3; - u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1; - u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2); + + if (adreno_is_a650_family(adreno_gpu) || adreno_is_a7xx(adreno_gpu)) + uavflagprd_inv = 2; + + if (adreno_is_a610(adreno_gpu) || adreno_is_a702(adreno_gpu)) + min_acc_len_64b = true; gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL, level2_swizzling_dis << 12 | - adreno_gpu->ubwc_config.rgb565_predicator << 11 | - hbb_hi << 10 | adreno_gpu->ubwc_config.amsbc << 4 | - adreno_gpu->ubwc_config.min_acc_len << 3 | + rgb565_predicator << 11 | + hbb_hi << 10 | amsbc << 4 | + min_acc_len_64b << 3 | hbb_lo << 1 | ubwc_mode); gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, level2_swizzling_dis << 6 | hbb_hi << 4 | - adreno_gpu->ubwc_config.min_acc_len << 3 | + min_acc_len_64b << 3 | hbb_lo << 1 | ubwc_mode); gpu_write(gpu, REG_A6XX_SP_NC_MODE_CNTL, level2_swizzling_dis << 12 | hbb_hi << 10 | - adreno_gpu->ubwc_config.uavflagprd_inv << 4 | - adreno_gpu->ubwc_config.min_acc_len << 3 | + uavflagprd_inv << 4 | + min_acc_len_64b << 3 | hbb_lo << 1 | ubwc_mode); if (adreno_is_a7xx(adreno_gpu)) @@ -696,10 +854,10 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu) FIELD_PREP(GENMASK(8, 5), hbb_lo)); gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL, - adreno_gpu->ubwc_config.min_acc_len << 23 | hbb_lo << 21); + min_acc_len_64b << 23 | hbb_lo << 21); gpu_write(gpu, REG_A6XX_RBBM_NC_MODE_CNTL, - adreno_gpu->ubwc_config.macrotile_mode); + cfg->macrotile_mode); } static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu) @@ -712,11 +870,10 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu) u32 *dest = (u32 *)&lock->regs[0]; int i; - reglist = adreno_gpu->info->a6xx->pwrup_reglist; - lock->gpu_req = lock->cpu_req = lock->turn = 0; - lock->ifpc_list_len = 0; - lock->preemption_list_len = reglist->count; + + reglist = adreno_gpu->info->a6xx->ifpc_reglist; + lock->ifpc_list_len = reglist->count; /* * For each entry in each of the lists, write the offset and the current @@ -727,6 +884,14 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu) *dest++ = gpu_read(gpu, reglist->regs[i]); } + reglist = adreno_gpu->info->a6xx->pwrup_reglist; + lock->preemption_list_len = reglist->count; + + for (i = 0; i < reglist->count; i++) { + *dest++ = reglist->regs[i]; + *dest++ = gpu_read(gpu, reglist->regs[i]); + } + /* * The overall register list is composed of * 1. Static IFPC-only registers @@ -870,7 +1035,7 @@ static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu, return false; /* A7xx is safe! */ - if (adreno_is_a7xx(adreno_gpu) || adreno_is_a702(adreno_gpu)) + if (adreno_is_a7xx(adreno_gpu) || adreno_is_a702(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) return true; /* @@ -945,7 +1110,7 @@ static int a6xx_ucode_load(struct msm_gpu *gpu) msm_gem_object_set_name(a6xx_gpu->sqe_bo, "sqefw"); if (!a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo)) { - msm_gem_unpin_iova(a6xx_gpu->sqe_bo, gpu->aspace); + msm_gem_unpin_iova(a6xx_gpu->sqe_bo, gpu->vm); drm_gem_object_put(a6xx_gpu->sqe_bo); a6xx_gpu->sqe_bo = NULL; @@ -953,6 +1118,23 @@ static int a6xx_ucode_load(struct msm_gpu *gpu) } } + if (!a6xx_gpu->aqe_bo && adreno_gpu->fw[ADRENO_FW_AQE]) { + a6xx_gpu->aqe_bo = adreno_fw_create_bo(gpu, + adreno_gpu->fw[ADRENO_FW_AQE], &a6xx_gpu->aqe_iova); + + if (IS_ERR(a6xx_gpu->aqe_bo)) { + int ret = PTR_ERR(a6xx_gpu->aqe_bo); + + a6xx_gpu->aqe_bo = NULL; + DRM_DEV_ERROR(&gpu->pdev->dev, + "Could not allocate AQE ucode: %d\n", ret); + + return ret; + } + + msm_gem_object_set_name(a6xx_gpu->aqe_bo, "aqefw"); + } + /* * Expanded APRIV and targets that support WHERE_AM_I both need a * privileged buffer to store the RPTR shadow @@ -962,7 +1144,7 @@ static int a6xx_ucode_load(struct msm_gpu *gpu) a6xx_gpu->shadow = msm_gem_kernel_new(gpu->dev, sizeof(u32) * gpu->nr_rings, MSM_BO_WC | MSM_BO_MAP_PRIV, - gpu->aspace, &a6xx_gpu->shadow_bo, + gpu->vm, &a6xx_gpu->shadow_bo, &a6xx_gpu->shadow_iova); if (IS_ERR(a6xx_gpu->shadow)) @@ -973,7 +1155,7 @@ static int a6xx_ucode_load(struct msm_gpu *gpu) a6xx_gpu->pwrup_reglist_ptr = msm_gem_kernel_new(gpu->dev, PAGE_SIZE, MSM_BO_WC | MSM_BO_MAP_PRIV, - gpu->aspace, &a6xx_gpu->pwrup_reglist_bo, + gpu->vm, &a6xx_gpu->pwrup_reglist_bo, &a6xx_gpu->pwrup_reglist_iova); if (IS_ERR(a6xx_gpu->pwrup_reglist_ptr)) @@ -984,7 +1166,7 @@ static int a6xx_ucode_load(struct msm_gpu *gpu) return 0; } -static int a6xx_zap_shader_init(struct msm_gpu *gpu) +int a6xx_zap_shader_init(struct msm_gpu *gpu) { static bool loaded; int ret; @@ -1097,17 +1279,20 @@ static int hw_init(struct msm_gpu *gpu) /* enable hardware clockgating */ a6xx_set_hwcg(gpu, true); - /* VBIF/GBIF start*/ - if (adreno_is_a610_family(adreno_gpu) || - adreno_is_a640_family(adreno_gpu) || - adreno_is_a650_family(adreno_gpu) || - adreno_is_a7xx(adreno_gpu)) { + /* For gmuwrapper implementations, do the VBIF/GBIF CX configuration here */ + if (adreno_is_a610_family(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, - adreno_is_a7xx(adreno_gpu) ? 0x2120212 : 0x3); + } + + if (adreno_is_a610_family(adreno_gpu) || + adreno_is_a640_family(adreno_gpu) || + adreno_is_a650_family(adreno_gpu)) { + gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x3); + } else if (adreno_is_a7xx(adreno_gpu)) { + gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x2120212); } else { gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3); } @@ -1123,12 +1308,12 @@ static int hw_init(struct msm_gpu *gpu) /* Disable L2 bypass in the UCHE */ 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); + gpu_write64(gpu, REG_A6XX_UCHE_TRAP_BASE, adreno_gpu->uche_trap_base); + gpu_write64(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE, adreno_gpu->uche_trap_base); } 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); + gpu_write64(gpu, REG_A6XX_UCHE_WRITE_RANGE_MAX, adreno_gpu->uche_trap_base + 0xfc0); + gpu_write64(gpu, REG_A6XX_UCHE_TRAP_BASE, adreno_gpu->uche_trap_base); + gpu_write64(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE, adreno_gpu->uche_trap_base); } if (!(adreno_is_a650_family(adreno_gpu) || @@ -1162,10 +1347,10 @@ static int hw_init(struct msm_gpu *gpu) } if (adreno_is_a660_family(adreno_gpu)) - gpu_write(gpu, REG_A6XX_CP_LPAC_PROG_FIFO_SIZE, 0x00000020); + gpu_write(gpu, REG_A7XX_CP_LPAC_PROG_FIFO_SIZE, 0x00000020); /* Setting the mem pool size */ - if (adreno_is_a610(adreno_gpu)) { + if (adreno_is_a610(adreno_gpu) || adreno_is_a612(adreno_gpu)) { gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 48); gpu_write(gpu, REG_A6XX_CP_MEM_POOL_DBG_ADDR, 47); } else if (adreno_is_a702(adreno_gpu)) { @@ -1198,7 +1383,8 @@ static int hw_init(struct msm_gpu *gpu) a6xx_set_ubwc_config(gpu); /* Enable fault detection */ - if (adreno_is_a730(adreno_gpu) || + if (adreno_is_a612(adreno_gpu) || + 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)) @@ -1214,14 +1400,14 @@ static int hw_init(struct msm_gpu *gpu) /* Set weights for bicubic filtering */ if (adreno_is_a650_family(adreno_gpu) || adreno_is_x185(adreno_gpu)) { - gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0, 0); - gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1, + gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(0), 0); + gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(1), 0x3fe05ff4); - gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2, + gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(2), 0x3fa0ebee); - gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3, + gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(3), 0x3f5193ed); - gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4, + gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(4), 0x3f0243f0); } @@ -1417,25 +1603,25 @@ static void a6xx_recover(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; - int i, active_submits; + int active_submits; adreno_dump_info(gpu); - for (i = 0; i < 8; i++) - DRM_DEV_INFO(&gpu->pdev->dev, "CP_SCRATCH_REG%d: %u\n", i, - gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(i))); + if (a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) { + /* Sometimes crashstate capture is skipped, so SQE should be halted here again */ + gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3); + + if (hang_debug) + a6xx_dump(gpu); - if (hang_debug) - a6xx_dump(gpu); + } /* * To handle recovery specific sequences during the rpm suspend we are * about to trigger */ - a6xx_gpu->hung = true; - /* Halt SQE first */ - gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3); + a6xx_gpu->hung = true; pm_runtime_dont_use_autosuspend(&gpu->pdev->dev); @@ -1449,9 +1635,9 @@ static void a6xx_recover(struct msm_gpu *gpu) */ gpu->active_submits = 0; - if (adreno_has_gmu_wrapper(adreno_gpu)) { + if (adreno_has_gmu_wrapper(adreno_gpu) || adreno_has_rgmu(adreno_gpu)) { /* Drain the outstanding traffic on memory buses */ - a6xx_bus_clear_pending_transactions(adreno_gpu, true); + adreno_gpu->funcs->bus_halt(adreno_gpu, true); /* Reset the GPU to a clean state */ a6xx_gpu_sw_reset(gpu, true); @@ -1610,10 +1796,10 @@ static int a6xx_fault_handler(void *arg, unsigned long iova, int flags, void *da const char *block = "unknown"; u32 scratch[] = { - gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(4)), - gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(5)), - gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(6)), - gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(7)), + gpu_read(gpu, REG_A6XX_CP_SCRATCH(4)), + gpu_read(gpu, REG_A6XX_CP_SCRATCH(5)), + gpu_read(gpu, REG_A6XX_CP_SCRATCH(6)), + gpu_read(gpu, REG_A6XX_CP_SCRATCH(7)), }; if (info) @@ -1666,8 +1852,6 @@ static void a6xx_cp_hw_err_irq(struct msm_gpu *gpu) static void a6xx_fault_detect_irq(struct msm_gpu *gpu) { - struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu); /* @@ -1679,13 +1863,6 @@ static void a6xx_fault_detect_irq(struct msm_gpu *gpu) if (gpu_read(gpu, REG_A6XX_RBBM_STATUS3) & A6XX_RBBM_STATUS3_SMMU_STALLED_ON_FAULT) return; - /* - * Force the GPU to stay on until after we finish - * collecting information - */ - if (!adreno_has_gmu_wrapper(adreno_gpu)) - gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 1); - DRM_DEV_ERROR(&gpu->pdev->dev, "gpu fault ring %d fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n", ring ? ring->id : -1, ring ? ring->fctx->last_fence : 0, @@ -1698,7 +1875,10 @@ static void a6xx_fault_detect_irq(struct msm_gpu *gpu) gpu_read(gpu, REG_A6XX_CP_IB2_REM_SIZE)); /* Turn off the hangcheck timer to keep it from bothering us */ - del_timer(&gpu->hangcheck_timer); + timer_delete(&gpu->hangcheck_timer); + + /* Turn off interrupts to avoid triggering recovery again */ + gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, 0); kthread_queue_work(gpu->worker, &gpu->recover_work); } @@ -1718,15 +1898,55 @@ static void a7xx_sw_fuse_violation_irq(struct msm_gpu *gpu) */ if (status & (A7XX_CX_MISC_SW_FUSE_VALUE_RAYTRACING | A7XX_CX_MISC_SW_FUSE_VALUE_LPAC)) { - del_timer(&gpu->hangcheck_timer); + timer_delete(&gpu->hangcheck_timer); kthread_queue_work(gpu->worker, &gpu->recover_work); } } +static void a6xx_gpu_keepalive_vote(struct msm_gpu *gpu, bool on) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + + if (adreno_has_gmu_wrapper(adreno_gpu)) + return; + + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, on); +} + +static int irq_poll_fence(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; + u32 status; + + if (adreno_has_gmu_wrapper(adreno_gpu)) + return 0; + + if (gmu_poll_timeout_atomic(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, status, !status, 1, 100)) { + u32 rbbm_unmasked = gmu_read(gmu, REG_A6XX_GMU_RBBM_INT_UNMASKED_STATUS); + + dev_err_ratelimited(&gpu->pdev->dev, + "irq fence poll timeout, fence_ctrl=0x%x, unmasked_status=0x%x\n", + status, rbbm_unmasked); + return -ETIMEDOUT; + } + + return 0; +} + static irqreturn_t a6xx_irq(struct msm_gpu *gpu) { struct msm_drm_private *priv = gpu->dev->dev_private; + + /* Set keepalive vote to avoid power collapse after RBBM_INT_0_STATUS is read */ + a6xx_gpu_keepalive_vote(gpu, true); + + if (irq_poll_fence(gpu)) + goto done; + u32 status = gpu_read(gpu, REG_A6XX_RBBM_INT_0_STATUS); gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status); @@ -1763,6 +1983,9 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu) if (status & A6XX_RBBM_INT_0_MASK_CP_SW) a6xx_preempt_irq(gpu); +done: + a6xx_gpu_keepalive_vote(gpu, false); + return IRQ_HANDLED; } @@ -1908,7 +2131,7 @@ static int a7xx_cx_mem_init(struct a6xx_gpu *a6xx_gpu) u32 fuse_val; int ret; - if (adreno_is_a750(adreno_gpu)) { + if (adreno_is_a750(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) { /* * Assume that if qcom scm isn't available, that whatever * replacement allows writing the fuse register ourselves. @@ -1934,9 +2157,9 @@ static int a7xx_cx_mem_init(struct a6xx_gpu *a6xx_gpu) return ret; /* - * On a750 raytracing may be disabled by the firmware, find out - * whether that's the case. The scm call above sets the fuse - * register. + * On A7XX_GEN3 and newer, raytracing may be disabled by the + * firmware, find out whether that's the case. The scm call + * above sets the fuse register. */ fuse_val = a6xx_llc_read(a6xx_gpu, REG_A7XX_CX_MISC_SW_FUSE_VALUE); @@ -1997,7 +2220,7 @@ void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_ void a6xx_gpu_sw_reset(struct msm_gpu *gpu, bool assert) { /* 11nm chips (e.g. ones with A610) have hw issues with the reset line! */ - if (adreno_is_a610(to_adreno_gpu(gpu))) + if (adreno_is_a610(to_adreno_gpu(gpu)) || adreno_is_a8xx(to_adreno_gpu(gpu))) return; gpu_write(gpu, REG_A6XX_RBBM_SW_RESET_CMD, assert); @@ -2028,7 +2251,12 @@ static int a6xx_gmu_pm_resume(struct msm_gpu *gpu) msm_devfreq_resume(gpu); - adreno_is_a7xx(adreno_gpu) ? a7xx_llc_activate(a6xx_gpu) : a6xx_llc_activate(a6xx_gpu); + if (adreno_is_a8xx(adreno_gpu)) + a8xx_llc_activate(a6xx_gpu); + else if (adreno_is_a7xx(adreno_gpu)) + a7xx_llc_activate(a6xx_gpu); + else + a6xx_llc_activate(a6xx_gpu); return ret; } @@ -2065,6 +2293,12 @@ static int a6xx_pm_resume(struct msm_gpu *gpu) if (ret) goto err_bulk_clk; + ret = clk_bulk_prepare_enable(gmu->nr_clocks, gmu->clocks); + if (ret) { + clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks); + goto err_bulk_clk; + } + if (adreno_is_a619_holi(adreno_gpu)) a6xx_sptprac_enable(gmu); @@ -2078,8 +2312,10 @@ err_bulk_clk: err_set_opp: mutex_unlock(&a6xx_gpu->gmu.lock); - if (!ret) + if (!ret) { msm_devfreq_resume(gpu); + a6xx_llc_activate(a6xx_gpu); + } return ret; } @@ -2120,17 +2356,20 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu) trace_msm_gpu_suspend(0); + a6xx_llc_deactivate(a6xx_gpu); + msm_devfreq_suspend(gpu); mutex_lock(&a6xx_gpu->gmu.lock); /* Drain the outstanding traffic on memory buses */ - a6xx_bus_clear_pending_transactions(adreno_gpu, true); + adreno_gpu->funcs->bus_halt(adreno_gpu, true); if (adreno_is_a619_holi(adreno_gpu)) a6xx_sptprac_disable(gmu); clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks); + clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks); pm_runtime_put_sync(gmu->gxpd); dev_pm_opp_set_opp(&gpu->pdev->dev, NULL); @@ -2152,16 +2391,7 @@ static int a6xx_gmu_get_timestamp(struct msm_gpu *gpu, uint64_t *value) struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); - mutex_lock(&a6xx_gpu->gmu.lock); - - /* Force the GPU power on so we can read this register */ - a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); - - *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER); - - a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); - - mutex_unlock(&a6xx_gpu->gmu.lock); + *value = read_gmu_ao_counter(a6xx_gpu); return 0; } @@ -2186,12 +2416,17 @@ static void a6xx_destroy(struct msm_gpu *gpu) struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); if (a6xx_gpu->sqe_bo) { - msm_gem_unpin_iova(a6xx_gpu->sqe_bo, gpu->aspace); + msm_gem_unpin_iova(a6xx_gpu->sqe_bo, gpu->vm); drm_gem_object_put(a6xx_gpu->sqe_bo); } + if (a6xx_gpu->aqe_bo) { + msm_gem_unpin_iova(a6xx_gpu->aqe_bo, gpu->vm); + drm_gem_object_put(a6xx_gpu->aqe_bo); + } + if (a6xx_gpu->shadow_bo) { - msm_gem_unpin_iova(a6xx_gpu->shadow_bo, gpu->aspace); + msm_gem_unpin_iova(a6xx_gpu->shadow_bo, gpu->vm); drm_gem_object_put(a6xx_gpu->shadow_bo); } @@ -2231,8 +2466,8 @@ static void a6xx_gpu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp, mutex_unlock(&a6xx_gpu->gmu.lock); } -static struct msm_gem_address_space * -a6xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev) +static struct drm_gpuvm * +a6xx_create_vm(struct msm_gpu *gpu, struct platform_device *pdev) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); @@ -2246,22 +2481,21 @@ a6xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev) !device_iommu_capable(&pdev->dev, IOMMU_CAP_CACHE_COHERENCY)) quirks |= IO_PGTABLE_QUIRK_ARM_OUTER_WBWA; - return adreno_iommu_create_address_space(gpu, pdev, quirks); + return adreno_iommu_create_vm(gpu, pdev, quirks); } -static struct msm_gem_address_space * -a6xx_create_private_address_space(struct msm_gpu *gpu) +static struct drm_gpuvm * +a6xx_create_private_vm(struct msm_gpu *gpu, bool kernel_managed) { struct msm_mmu *mmu; - mmu = msm_iommu_pagetable_create(gpu->aspace->mmu); + mmu = msm_iommu_pagetable_create(to_msm_vm(gpu->vm)->mmu, kernel_managed); if (IS_ERR(mmu)) return ERR_CAST(mmu); - return msm_gem_address_space_create(mmu, - "gpu", 0x100000000ULL, - adreno_private_address_space_size(gpu)); + return msm_gem_vm_create(gpu->dev, mmu, "gpu", ADRENO_VM_START, + adreno_private_vm_size(gpu), kernel_managed); } static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) @@ -2272,18 +2506,36 @@ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami) return a6xx_gpu->shadow[ring->id]; + /* + * This is true only on an A6XX_GEN1 with GMU, has IFPC enabled and a super old SQE firmware + * without 'whereami' support + */ + WARN_ONCE((to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC), + "Can't read CP_RB_RPTR register reliably\n"); + return ring->memptrs->rptr = gpu_read(gpu, REG_A6XX_CP_RB_RPTR); } static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring) { - struct msm_cp_state cp_state = { + struct msm_cp_state cp_state; + bool progress; + + /* + * With IFPC, KMD doesn't know whether GX power domain is collapsed + * or not. So, we can't blindly read the below registers in GX domain. + * Lets trust the hang detection in HW and lie to the caller that + * there was progress. + */ + if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC) + return true; + + cp_state = (struct msm_cp_state) { .ib1_base = gpu_read64(gpu, REG_A6XX_CP_IB1_BASE), .ib2_base = gpu_read64(gpu, REG_A6XX_CP_IB2_BASE), .ib1_rem = gpu_read(gpu, REG_A6XX_CP_IB1_REM_SIZE), .ib2_rem = gpu_read(gpu, REG_A6XX_CP_IB2_REM_SIZE), }; - bool progress; /* * Adjust the remaining data to account for what has already been @@ -2355,7 +2607,105 @@ static int a6xx_set_supported_hw(struct device *dev, const struct adreno_info *i return 0; } -static const struct adreno_gpu_funcs funcs = { +static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) +{ + struct msm_drm_private *priv = dev->dev_private; + struct platform_device *pdev = priv->gpu_pdev; + struct adreno_platform_config *config = pdev->dev.platform_data; + struct device_node *node; + struct a6xx_gpu *a6xx_gpu; + struct adreno_gpu *adreno_gpu; + struct msm_gpu *gpu; + extern int enable_preemption; + bool is_a7xx; + int ret, nr_rings = 1; + + a6xx_gpu = kzalloc(sizeof(*a6xx_gpu), GFP_KERNEL); + if (!a6xx_gpu) + return ERR_PTR(-ENOMEM); + + adreno_gpu = &a6xx_gpu->base; + gpu = &adreno_gpu->base; + + mutex_init(&a6xx_gpu->gmu.lock); + + adreno_gpu->registers = NULL; + + /* Check if there is a GMU phandle and set it up */ + node = of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0); + /* FIXME: How do we gracefully handle this? */ + BUG_ON(!node); + + adreno_gpu->gmu_is_wrapper = of_device_is_compatible(node, "qcom,adreno-gmu-wrapper"); + + adreno_gpu->base.hw_apriv = + !!(config->info->quirks & ADRENO_QUIRK_HAS_HW_APRIV); + + /* gpu->info only gets assigned in adreno_gpu_init(). A8x is included intentionally */ + is_a7xx = config->info->family >= ADRENO_7XX_GEN1; + + a6xx_llc_slices_init(pdev, a6xx_gpu, is_a7xx); + + ret = a6xx_set_supported_hw(&pdev->dev, config->info); + if (ret) { + a6xx_llc_slices_destroy(a6xx_gpu); + kfree(a6xx_gpu); + return ERR_PTR(ret); + } + + if ((enable_preemption == 1) || (enable_preemption == -1 && + (config->info->quirks & ADRENO_QUIRK_PREEMPTION))) + nr_rings = 4; + + ret = adreno_gpu_init(dev, pdev, adreno_gpu, config->info->funcs, nr_rings); + if (ret) { + a6xx_destroy(&(a6xx_gpu->base.base)); + return ERR_PTR(ret); + } + + /* + * For now only clamp to idle freq for devices where this is known not + * to cause power supply issues: + */ + if (adreno_is_a618(adreno_gpu) || adreno_is_7c3(adreno_gpu)) + priv->gpu_clamp_to_idle = true; + + if (adreno_has_gmu_wrapper(adreno_gpu) || adreno_has_rgmu(adreno_gpu)) + ret = a6xx_gmu_wrapper_init(a6xx_gpu, node); + else + ret = a6xx_gmu_init(a6xx_gpu, node); + of_node_put(node); + if (ret) { + a6xx_destroy(&(a6xx_gpu->base.base)); + return ERR_PTR(ret); + } + + if (adreno_is_a7xx(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) { + ret = a7xx_cx_mem_init(a6xx_gpu); + if (ret) { + a6xx_destroy(&(a6xx_gpu->base.base)); + return ERR_PTR(ret); + } + } + + adreno_gpu->uche_trap_base = 0x1fffffffff000ull; + + msm_mmu_set_fault_handler(to_msm_vm(gpu->vm)->mmu, gpu, + adreno_gpu->funcs->mmu_fault_handler); + + ret = a6xx_calc_ubwc_config(adreno_gpu); + if (ret) { + a6xx_destroy(&(a6xx_gpu->base.base)); + return ERR_PTR(ret); + } + + /* Set up the preemption specific bits and pieces for each ringbuffer */ + a6xx_preempt_init(gpu); + + return gpu; +} + +const struct adreno_gpu_funcs a6xx_gpu_funcs = { .base = { .get_param = adreno_get_param, .set_param = adreno_set_param, @@ -2378,15 +2728,18 @@ static const struct adreno_gpu_funcs funcs = { .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, + .create_vm = a6xx_create_vm, + .create_private_vm = a6xx_create_private_vm, .get_rptr = a6xx_get_rptr, .progress = a6xx_progress, }, + .init = a6xx_gpu_init, .get_timestamp = a6xx_gmu_get_timestamp, + .bus_halt = a6xx_bus_clear_pending_transactions, + .mmu_fault_handler = a6xx_fault_handler, }; -static const struct adreno_gpu_funcs funcs_gmuwrapper = { +const struct adreno_gpu_funcs a6xx_gmuwrapper_funcs = { .base = { .get_param = adreno_get_param, .set_param = adreno_set_param, @@ -2407,15 +2760,18 @@ static const struct adreno_gpu_funcs funcs_gmuwrapper = { .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, + .create_vm = a6xx_create_vm, + .create_private_vm = a6xx_create_private_vm, .get_rptr = a6xx_get_rptr, .progress = a6xx_progress, }, + .init = a6xx_gpu_init, .get_timestamp = a6xx_get_timestamp, + .bus_halt = a6xx_bus_clear_pending_transactions, + .mmu_fault_handler = a6xx_fault_handler, }; -static const struct adreno_gpu_funcs funcs_a7xx = { +const struct adreno_gpu_funcs a7xx_gpu_funcs = { .base = { .get_param = adreno_get_param, .set_param = adreno_set_param, @@ -2438,108 +2794,40 @@ static const struct adreno_gpu_funcs funcs_a7xx = { .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, + .create_vm = a6xx_create_vm, + .create_private_vm = a6xx_create_private_vm, .get_rptr = a6xx_get_rptr, .progress = a6xx_progress, }, + .init = a6xx_gpu_init, .get_timestamp = a6xx_gmu_get_timestamp, + .bus_halt = a6xx_bus_clear_pending_transactions, + .mmu_fault_handler = a6xx_fault_handler, }; -struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct platform_device *pdev = priv->gpu_pdev; - struct adreno_platform_config *config = pdev->dev.platform_data; - struct device_node *node; - struct a6xx_gpu *a6xx_gpu; - struct adreno_gpu *adreno_gpu; - struct msm_gpu *gpu; - extern int enable_preemption; - bool is_a7xx; - int ret; - - a6xx_gpu = kzalloc(sizeof(*a6xx_gpu), GFP_KERNEL); - if (!a6xx_gpu) - return ERR_PTR(-ENOMEM); - - adreno_gpu = &a6xx_gpu->base; - gpu = &adreno_gpu->base; - - mutex_init(&a6xx_gpu->gmu.lock); - - adreno_gpu->registers = NULL; - - /* Check if there is a GMU phandle and set it up */ - node = of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0); - /* FIXME: How do we gracefully handle this? */ - BUG_ON(!node); - - adreno_gpu->gmu_is_wrapper = of_device_is_compatible(node, "qcom,adreno-gmu-wrapper"); - - adreno_gpu->base.hw_apriv = - !!(config->info->quirks & ADRENO_QUIRK_HAS_HW_APRIV); - - /* gpu->info only gets assigned in adreno_gpu_init() */ - is_a7xx = config->info->family == ADRENO_7XX_GEN1 || - config->info->family == ADRENO_7XX_GEN2 || - config->info->family == ADRENO_7XX_GEN3; - - a6xx_llc_slices_init(pdev, a6xx_gpu, is_a7xx); - - ret = a6xx_set_supported_hw(&pdev->dev, config->info); - if (ret) { - a6xx_llc_slices_destroy(a6xx_gpu); - kfree(a6xx_gpu); - return ERR_PTR(ret); - } - - if ((enable_preemption == 1) || (enable_preemption == -1 && - (config->info->quirks & ADRENO_QUIRK_PREEMPTION))) - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_a7xx, 4); - else 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); - if (ret) { - a6xx_destroy(&(a6xx_gpu->base.base)); - return ERR_PTR(ret); - } - - /* - * For now only clamp to idle freq for devices where this is known not - * to cause power supply issues: - */ - if (adreno_is_a618(adreno_gpu) || adreno_is_7c3(adreno_gpu)) - priv->gpu_clamp_to_idle = true; - - if (adreno_has_gmu_wrapper(adreno_gpu)) - ret = a6xx_gmu_wrapper_init(a6xx_gpu, node); - else - ret = a6xx_gmu_init(a6xx_gpu, node); - of_node_put(node); - if (ret) { - a6xx_destroy(&(a6xx_gpu->base.base)); - return ERR_PTR(ret); - } - - if (adreno_is_a7xx(adreno_gpu)) { - ret = a7xx_cx_mem_init(a6xx_gpu); - if (ret) { - a6xx_destroy(&(a6xx_gpu->base.base)); - return ERR_PTR(ret); - } - } - - if (gpu->aspace) - msm_mmu_set_fault_handler(gpu->aspace->mmu, gpu, - a6xx_fault_handler); - - a6xx_calc_ubwc_config(adreno_gpu); - /* Set up the preemption specific bits and pieces for each ringbuffer */ - a6xx_preempt_init(gpu); - - return gpu; -} +const struct adreno_gpu_funcs a8xx_gpu_funcs = { + .base = { + .get_param = adreno_get_param, + .set_param = adreno_set_param, + .hw_init = a8xx_hw_init, + .ucode_load = a6xx_ucode_load, + .pm_suspend = a6xx_gmu_pm_suspend, + .pm_resume = a6xx_gmu_pm_resume, + .recover = a8xx_recover, + .submit = a7xx_submit, + .active_ring = a6xx_active_ring, + .irq = a8xx_irq, + .destroy = a6xx_destroy, + .gpu_busy = a8xx_gpu_busy, + .gpu_get_freq = a6xx_gmu_get_freq, + .gpu_set_freq = a6xx_gpu_set_freq, + .create_vm = a6xx_create_vm, + .create_private_vm = a6xx_create_private_vm, + .get_rptr = a6xx_get_rptr, + .progress = a8xx_progress, + }, + .init = a6xx_gpu_init, + .get_timestamp = a8xx_gmu_get_timestamp, + .bus_halt = a8xx_bus_clear_pending_transactions, + .mmu_fault_handler = a8xx_fault_handler, +}; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h index 4aceffb6aae8..6820216ec5fc 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h @@ -6,6 +6,10 @@ #include "adreno_gpu.h" +#include "a6xx_enums.xml.h" +#include "a7xx_enums.xml.h" +#include "a6xx_perfcntrs.xml.h" +#include "a7xx_perfcntrs.xml.h" #include "a6xx.xml.h" #include "a6xx_gmu.h" @@ -41,9 +45,14 @@ struct a6xx_info { const struct adreno_reglist *hwcg; const struct adreno_protect *protect; const struct adreno_reglist_list *pwrup_reglist; + const struct adreno_reglist_list *ifpc_reglist; + const struct adreno_reglist *gbif_cx; + const struct adreno_reglist_pipe *nonctxt_reglist; + u32 max_slices; u32 gmu_chipid; u32 gmu_cgc_mode; u32 prim_fifo_threshold; + const struct a6xx_bcm *bcms; }; struct a6xx_gpu { @@ -51,6 +60,8 @@ struct a6xx_gpu { struct drm_gem_object *sqe_bo; uint64_t sqe_iova; + struct drm_gem_object *aqe_bo; + uint64_t aqe_iova; struct msm_ringbuffer *cur_ring; struct msm_ringbuffer *next_ring; @@ -95,6 +106,11 @@ struct a6xx_gpu { void *htw_llc_slice; bool have_mmu500; bool hung; + + u32 cached_aperture; + spinlock_t aperture_lock; + + u32 slice_mask; }; #define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base) @@ -210,6 +226,11 @@ struct a7xx_cp_smmu_info { #define A6XX_PROTECT_RDONLY(_reg, _len) \ ((((_len) & 0x3FFF) << 18) | ((_reg) & 0x3FFFF)) +extern const struct adreno_gpu_funcs a6xx_gpu_funcs; +extern const struct adreno_gpu_funcs a6xx_gmuwrapper_funcs; +extern const struct adreno_gpu_funcs a7xx_gpu_funcs; +extern const struct adreno_gpu_funcs a8xx_gpu_funcs; + static inline bool a6xx_has_gbif(struct adreno_gpu *gpu) { if(adreno_is_a630(gpu)) @@ -249,6 +270,7 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state); int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node); int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node); void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu); +void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu); void a6xx_preempt_init(struct msm_gpu *gpu); void a6xx_preempt_hw_init(struct msm_gpu *gpu); @@ -290,5 +312,20 @@ int a6xx_gpu_state_put(struct msm_gpu_state *state); void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off); void a6xx_gpu_sw_reset(struct msm_gpu *gpu, bool assert); - +int a6xx_fenced_write(struct a6xx_gpu *gpu, u32 offset, u64 value, u32 mask, bool is_64b); +void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring); +int a6xx_zap_shader_init(struct msm_gpu *gpu); + +void a8xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off); +int a8xx_fault_handler(void *arg, unsigned long iova, int flags, void *data); +void a8xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring); +int a8xx_gmu_get_timestamp(struct msm_gpu *gpu, uint64_t *value); +u64 a8xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate); +int a8xx_gpu_feature_probe(struct msm_gpu *gpu); +void a8xx_gpu_get_slice_info(struct msm_gpu *gpu); +int a8xx_hw_init(struct msm_gpu *gpu); +irqreturn_t a8xx_irq(struct msm_gpu *gpu); +void a8xx_llc_activate(struct a6xx_gpu *a6xx_gpu); +bool a8xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring); +void a8xx_recover(struct msm_gpu *gpu); #endif /* __A6XX_GPU_H__ */ diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 0fcae53c0b14..d2d6b2fd3cba 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -11,7 +11,7 @@ static const unsigned int *gen7_0_0_external_core_regs[] __always_unused; static const unsigned int *gen7_2_0_external_core_regs[] __always_unused; static const unsigned int *gen7_9_0_external_core_regs[] __always_unused; -static struct gen7_sptp_cluster_registers gen7_9_0_sptp_clusters[] __always_unused; +static const struct gen7_sptp_cluster_registers gen7_9_0_sptp_clusters[] __always_unused; static const u32 gen7_9_0_cx_debugbus_blocks[] __always_unused; #include "adreno_gen7_0_0_snapshot.h" @@ -132,7 +132,7 @@ static int a6xx_crashdumper_init(struct msm_gpu *gpu, struct a6xx_crashdumper *dumper) { dumper->ptr = msm_gem_kernel_new(gpu->dev, - SZ_1M, MSM_BO_WC, gpu->aspace, + SZ_1M, MSM_BO_WC, gpu->vm, &dumper->bo, &dumper->iova); if (!IS_ERR(dumper->ptr)) @@ -158,7 +158,7 @@ static int a6xx_crashdumper_run(struct msm_gpu *gpu, /* Make sure all pending memory writes are posted */ wmb(); - gpu_write64(gpu, REG_A6XX_CP_CRASH_SCRIPT_BASE, dumper->iova); + gpu_write64(gpu, REG_A6XX_CP_CRASH_DUMP_SCRIPT_BASE, dumper->iova); gpu_write(gpu, REG_A6XX_CP_CRASH_DUMP_CNTL, 1); @@ -174,8 +174,15 @@ static int a6xx_crashdumper_run(struct msm_gpu *gpu, static int debugbus_read(struct msm_gpu *gpu, u32 block, u32 offset, u32 *data) { - u32 reg = A6XX_DBGC_CFG_DBGBUS_SEL_D_PING_INDEX(offset) | - A6XX_DBGC_CFG_DBGBUS_SEL_D_PING_BLK_SEL(block); + u32 reg; + + if (to_adreno_gpu(gpu)->info->family >= ADRENO_7XX_GEN1) { + reg = A7XX_DBGC_CFG_DBGBUS_SEL_D_PING_INDEX(offset) | + A7XX_DBGC_CFG_DBGBUS_SEL_D_PING_BLK_SEL(block); + } else { + reg = A6XX_DBGC_CFG_DBGBUS_SEL_D_PING_INDEX(offset) | + A6XX_DBGC_CFG_DBGBUS_SEL_D_PING_BLK_SEL(block); + } gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_SEL_A, reg); gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_SEL_B, reg); @@ -198,11 +205,18 @@ static int debugbus_read(struct msm_gpu *gpu, u32 block, u32 offset, readl((ptr) + ((offset) << 2)) /* read a value from the CX debug bus */ -static int cx_debugbus_read(void __iomem *cxdbg, u32 block, u32 offset, +static int cx_debugbus_read(struct msm_gpu *gpu, void __iomem *cxdbg, u32 block, u32 offset, u32 *data) { - u32 reg = A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_INDEX(offset) | - A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_BLK_SEL(block); + u32 reg; + + if (to_adreno_gpu(gpu)->info->family >= ADRENO_7XX_GEN1) { + reg = A7XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_INDEX(offset) | + A7XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_BLK_SEL(block); + } else { + reg = A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_INDEX(offset) | + A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_BLK_SEL(block); + } cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_A, reg); cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_B, reg); @@ -315,7 +329,8 @@ static void a6xx_get_debugbus_block(struct msm_gpu *gpu, ptr += debugbus_read(gpu, block->id, i, ptr); } -static void a6xx_get_cx_debugbus_block(void __iomem *cxdbg, +static void a6xx_get_cx_debugbus_block(struct msm_gpu *gpu, + void __iomem *cxdbg, struct a6xx_gpu_state *a6xx_state, const struct a6xx_debugbus_block *block, struct a6xx_gpu_state_obj *obj) @@ -330,7 +345,7 @@ static void a6xx_get_cx_debugbus_block(void __iomem *cxdbg, obj->handle = block; for (ptr = obj->data, i = 0; i < block->count; i++) - ptr += cx_debugbus_read(cxdbg, block->id, i, ptr); + ptr += cx_debugbus_read(gpu, cxdbg, block->id, i, ptr); } static void a6xx_get_debugbus_blocks(struct msm_gpu *gpu, @@ -423,8 +438,9 @@ static void a7xx_get_debugbus_blocks(struct msm_gpu *gpu, a6xx_state, &a7xx_debugbus_blocks[gbif_debugbus_blocks[i]], &a6xx_state->debugbus[i + debugbus_blocks_count]); } - } + a6xx_state->nr_debugbus = total_debugbus_blocks; + } } static void a6xx_get_debugbus(struct msm_gpu *gpu, @@ -526,7 +542,8 @@ static void a6xx_get_debugbus(struct msm_gpu *gpu, int i; for (i = 0; i < nr_cx_debugbus_blocks; i++) - a6xx_get_cx_debugbus_block(cxdbg, + a6xx_get_cx_debugbus_block(gpu, + cxdbg, a6xx_state, &cx_debugbus_blocks[i], &a6xx_state->cx_debugbus[i]); @@ -759,15 +776,15 @@ static void a7xx_get_cluster(struct msm_gpu *gpu, size_t datasize; int i, regcount = 0; - /* Some clusters need a selector register to be programmed too */ - if (cluster->sel) - in += CRASHDUMP_WRITE(in, cluster->sel->cd_reg, cluster->sel->val); - in += CRASHDUMP_WRITE(in, REG_A7XX_CP_APERTURE_CNTL_CD, A7XX_CP_APERTURE_CNTL_CD_PIPE(cluster->pipe_id) | A7XX_CP_APERTURE_CNTL_CD_CLUSTER(cluster->cluster_id) | A7XX_CP_APERTURE_CNTL_CD_CONTEXT(cluster->context_id)); + /* Some clusters need a selector register to be programmed too */ + if (cluster->sel) + in += CRASHDUMP_WRITE(in, cluster->sel->cd_reg, cluster->sel->val); + for (i = 0; cluster->regs[i] != UINT_MAX; i += 2) { int count = RANGE(cluster->regs, i); @@ -1214,12 +1231,12 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); a6xx_state->gmu_registers = state_kcalloc(a6xx_state, - 3, sizeof(*a6xx_state->gmu_registers)); + 4, sizeof(*a6xx_state->gmu_registers)); if (!a6xx_state->gmu_registers) return; - a6xx_state->nr_gmu_registers = 3; + a6xx_state->nr_gmu_registers = 4; /* Get the CX GMU registers from AHB */ _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[0], @@ -1227,14 +1244,21 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[1], &a6xx_state->gmu_registers[1], true); + if (adreno_is_a621(adreno_gpu) || adreno_is_a623(adreno_gpu)) + _a6xx_get_gmu_registers(gpu, a6xx_state, &a621_gpucc_reg, + &a6xx_state->gmu_registers[2], false); + else + _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gpucc_reg, + &a6xx_state->gmu_registers[2], false); + if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) return; /* Set the fence to ALLOW mode so we can access the registers */ - gpu_write(gpu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0); + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0); _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[2], - &a6xx_state->gmu_registers[2], false); + &a6xx_state->gmu_registers[3], false); } static struct msm_gpu_state_bo *a6xx_snapshot_gmu_bo( @@ -1507,6 +1531,8 @@ 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, @@ -1560,8 +1586,7 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); struct a6xx_gpu_state *a6xx_state = kzalloc(sizeof(*a6xx_state), GFP_KERNEL); - bool stalled = !!(gpu_read(gpu, REG_A6XX_RBBM_STATUS3) & - A6XX_RBBM_STATUS3_SMMU_STALLED_ON_FAULT); + bool stalled; if (!a6xx_state) return ERR_PTR(-ENOMEM); @@ -1571,7 +1596,8 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) /* Get the generic state from the adreno core */ adreno_gpu_state_get(gpu, &a6xx_state->base); - if (!adreno_has_gmu_wrapper(adreno_gpu)) { + if (!adreno_has_gmu_wrapper(adreno_gpu) && + !adreno_has_rgmu(adreno_gpu)) { a6xx_get_gmu_registers(gpu, a6xx_state); a6xx_state->gmu_log = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.log); @@ -1582,15 +1608,20 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) } /* If GX isn't on the rest of the data isn't going to be accessible */ - if (!adreno_has_gmu_wrapper(adreno_gpu) && !a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) + if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) return &a6xx_state->base; + /* Halt SQE first */ + gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3); + /* Get the banks of indexed registers */ if (adreno_is_a7xx(adreno_gpu)) a7xx_get_indexed_registers(gpu, a6xx_state); else a6xx_get_indexed_registers(gpu, a6xx_state); + stalled = !!(gpu_read(gpu, REG_A6XX_RBBM_STATUS3) & + A6XX_RBBM_STATUS3_SMMU_STALLED_ON_FAULT); /* * Try to initialize the crashdumper, if we are not dumping state * with the SMMU stalled. The crashdumper needs memory access to @@ -1610,7 +1641,7 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) a7xx_get_clusters(gpu, a6xx_state, dumper); a7xx_get_dbgahb_clusters(gpu, a6xx_state, dumper); - msm_gem_kernel_put(dumper->bo, gpu->aspace); + msm_gem_kernel_put(dumper->bo, gpu->vm); } a7xx_get_post_crashdumper_registers(gpu, a6xx_state); @@ -1622,7 +1653,7 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) a6xx_get_clusters(gpu, a6xx_state, dumper); a6xx_get_dbgahb_clusters(gpu, a6xx_state, dumper); - msm_gem_kernel_put(dumper->bo, gpu->aspace); + msm_gem_kernel_put(dumper->bo, gpu->vm); } } @@ -1787,6 +1818,7 @@ static void a7xx_show_shader(struct a6xx_gpu_state_obj *obj, print_name(p, " - type: ", a7xx_statetype_names[block->statetype]); print_name(p, " - pipe: ", a7xx_pipe_names[block->pipeid]); + drm_printf(p, " - location: %d\n", block->location); for (i = 0; i < block->num_sps; i++) { drm_printf(p, " - sp: %d\n", i); @@ -1864,6 +1896,7 @@ static void a7xx_show_dbgahb_cluster(struct a6xx_gpu_state_obj *obj, print_name(p, " - pipe: ", a7xx_pipe_names[dbgahb->pipe_id]); print_name(p, " - cluster-name: ", a7xx_cluster_names[dbgahb->cluster_id]); drm_printf(p, " - context: %d\n", dbgahb->context_id); + drm_printf(p, " - location: %d\n", dbgahb->location_id); a7xx_show_registers_indented(dbgahb->regs, obj->data, p, 4); } } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h index dd4c28a8d923..b49d8427b59e 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h @@ -71,8 +71,8 @@ static const struct a6xx_cluster { u32 sel_val; } a6xx_clusters[] = { CLUSTER(CLUSTER_GRAS, a6xx_gras_cluster, 0, 0), - CLUSTER(CLUSTER_PS, a6xx_ps_cluster_rac, REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, 0x0), - CLUSTER(CLUSTER_PS, a6xx_ps_cluster_rbp, REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, 0x9), + CLUSTER(CLUSTER_PS, a6xx_ps_cluster_rac, REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, 0x0), + CLUSTER(CLUSTER_PS, a6xx_ps_cluster_rbp, REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, 0x9), CLUSTER(CLUSTER_PS, a6xx_ps_cluster, 0, 0), CLUSTER(CLUSTER_FE, a6xx_fe_cluster, 0, 0), CLUSTER(CLUSTER_PC_VS, a6xx_pc_vs_cluster, 0, 0), @@ -212,7 +212,7 @@ static const struct a6xx_shader_block { SHADER(A6XX_SP_LB_5_DATA, 0x200), SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x800), SHADER(A6XX_SP_CB_LEGACY_DATA, 0x280), - SHADER(A6XX_SP_UAV_DATA, 0x80), + SHADER(A6XX_SP_GFX_UAV_BASE_DATA, 0x80), SHADER(A6XX_SP_INST_TAG, 0x80), SHADER(A6XX_SP_CB_BINDLESS_TAG, 0x80), SHADER(A6XX_SP_TMO_UMO_TAG, 0x80), @@ -303,8 +303,8 @@ static const u32 a660_registers[] = { static const struct a6xx_registers a6xx_reglist[] = { REGS(a6xx_registers, 0, 0), REGS(a660_registers, 0, 0), - REGS(a6xx_rb_rac_registers, REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, 0), - REGS(a6xx_rb_rbp_registers, REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, 9), + REGS(a6xx_rb_rac_registers, REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, 0), + REGS(a6xx_rb_rbp_registers, REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, 9), }; static const u32 a6xx_ahb_registers[] = { @@ -343,34 +343,48 @@ static const struct a6xx_registers a6xx_gbif_reglist = static const u32 a6xx_gmu_gx_registers[] = { /* GMU GX */ - 0x0000, 0x0000, 0x0010, 0x0013, 0x0016, 0x0016, 0x0018, 0x001b, - 0x001e, 0x001e, 0x0020, 0x0023, 0x0026, 0x0026, 0x0028, 0x002b, - 0x002e, 0x002e, 0x0030, 0x0033, 0x0036, 0x0036, 0x0038, 0x003b, - 0x003e, 0x003e, 0x0040, 0x0043, 0x0046, 0x0046, 0x0080, 0x0084, - 0x0100, 0x012b, 0x0140, 0x0140, + 0x1a800, 0x1a800, 0x1a810, 0x1a813, 0x1a816, 0x1a816, 0x1a818, 0x1a81b, + 0x1a81e, 0x1a81e, 0x1a820, 0x1a823, 0x1a826, 0x1a826, 0x1a828, 0x1a82b, + 0x1a82e, 0x1a82e, 0x1a830, 0x1a833, 0x1a836, 0x1a836, 0x1a838, 0x1a83b, + 0x1a83e, 0x1a83e, 0x1a840, 0x1a843, 0x1a846, 0x1a846, 0x1a880, 0x1a884, + 0x1a900, 0x1a92b, 0x1a940, 0x1a940, }; static const u32 a6xx_gmu_cx_registers[] = { /* GMU CX */ - 0x4c00, 0x4c07, 0x4c10, 0x4c12, 0x4d00, 0x4d00, 0x4d07, 0x4d0a, - 0x5000, 0x5004, 0x5007, 0x5008, 0x500b, 0x500c, 0x500f, 0x501c, - 0x5024, 0x502a, 0x502d, 0x5030, 0x5040, 0x5053, 0x5087, 0x5089, - 0x50a0, 0x50a2, 0x50a4, 0x50af, 0x50c0, 0x50c3, 0x50d0, 0x50d0, - 0x50e4, 0x50e4, 0x50e8, 0x50ec, 0x5100, 0x5103, 0x5140, 0x5140, - 0x5142, 0x5144, 0x514c, 0x514d, 0x514f, 0x5151, 0x5154, 0x5154, - 0x5157, 0x5158, 0x515d, 0x515d, 0x5162, 0x5162, 0x5164, 0x5165, - 0x5180, 0x5186, 0x5190, 0x519e, 0x51c0, 0x51c0, 0x51c5, 0x51cc, - 0x51e0, 0x51e2, 0x51f0, 0x51f0, 0x5200, 0x5201, + 0x1f400, 0x1f407, 0x1f410, 0x1f412, 0x1f500, 0x1f500, 0x1f507, 0x1f50a, + 0x1f800, 0x1f804, 0x1f807, 0x1f808, 0x1f80b, 0x1f80c, 0x1f80f, 0x1f81c, + 0x1f824, 0x1f82a, 0x1f82d, 0x1f830, 0x1f840, 0x1f853, 0x1f887, 0x1f889, + 0x1f8a0, 0x1f8a2, 0x1f8a4, 0x1f8af, 0x1f8c0, 0x1f8c3, 0x1f8d0, 0x1f8d0, + 0x1f8e4, 0x1f8e4, 0x1f8e8, 0x1f8ec, 0x1f900, 0x1f903, 0x1f940, 0x1f940, + 0x1f942, 0x1f944, 0x1f94c, 0x1f94d, 0x1f94f, 0x1f951, 0x1f954, 0x1f954, + 0x1f957, 0x1f958, 0x1f95d, 0x1f95d, 0x1f962, 0x1f962, 0x1f964, 0x1f965, + 0x1f980, 0x1f986, 0x1f990, 0x1f99e, 0x1f9c0, 0x1f9c0, 0x1f9c5, 0x1f9cc, + 0x1f9e0, 0x1f9e2, 0x1f9f0, 0x1f9f0, 0x1fa00, 0x1fa01, /* GMU AO */ - 0x9300, 0x9316, 0x9400, 0x9400, + 0x23b00, 0x23b16, 0x23c00, 0x23c00, +}; + +static const u32 a6xx_gmu_gpucc_registers[] = { /* GPU CC */ - 0x9800, 0x9812, 0x9840, 0x9852, 0x9c00, 0x9c04, 0x9c07, 0x9c0b, - 0x9c15, 0x9c1c, 0x9c1e, 0x9c2d, 0x9c3c, 0x9c3d, 0x9c3f, 0x9c40, - 0x9c42, 0x9c49, 0x9c58, 0x9c5a, 0x9d40, 0x9d5e, 0xa000, 0xa002, - 0xa400, 0xa402, 0xac00, 0xac02, 0xb000, 0xb002, 0xb400, 0xb402, - 0xb800, 0xb802, + 0x24000, 0x24012, 0x24040, 0x24052, 0x24400, 0x24404, 0x24407, 0x2440b, + 0x24415, 0x2441c, 0x2441e, 0x2442d, 0x2443c, 0x2443d, 0x2443f, 0x24440, + 0x24442, 0x24449, 0x24458, 0x2445a, 0x24540, 0x2455e, 0x24800, 0x24802, + 0x24c00, 0x24c02, 0x25400, 0x25402, 0x25800, 0x25802, 0x25c00, 0x25c02, + 0x26000, 0x26002, /* GPU CC ACD */ - 0xbc00, 0xbc16, 0xbc20, 0xbc27, + 0x26400, 0x26416, 0x26420, 0x26427, +}; + +static const u32 a621_gmu_gpucc_registers[] = { + /* GPU CC */ + 0x24000, 0x2400e, 0x24400, 0x2440e, 0x25800, 0x25804, 0x25c00, 0x25c04, + 0x26000, 0x26004, 0x26400, 0x26405, 0x26414, 0x2641d, 0x2642a, 0x26430, + 0x26432, 0x26432, 0x26441, 0x26455, 0x26466, 0x26468, 0x26478, 0x2647a, + 0x26489, 0x2648a, 0x2649c, 0x2649e, 0x264a0, 0x264a3, 0x264b3, 0x264b5, + 0x264c5, 0x264c7, 0x264d6, 0x264d8, 0x264e8, 0x264e9, 0x264f9, 0x264fc, + 0x2650b, 0x2650c, 0x2651c, 0x2651e, 0x26540, 0x26570, 0x26600, 0x26616, + 0x26620, 0x2662d, }; static const u32 a6xx_gmu_cx_rscc_registers[] = { @@ -386,6 +400,9 @@ static const struct a6xx_registers a6xx_gmu_reglist[] = { REGS(a6xx_gmu_gx_registers, 0, 0), }; +static const struct a6xx_registers a6xx_gpucc_reg = REGS(a6xx_gmu_gpucc_registers, 0, 0); +static const struct a6xx_registers a621_gpucc_reg = REGS(a621_gmu_gpucc_registers, 0, 0); + static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu); static u32 a7xx_get_cp_roq_size(struct msm_gpu *gpu); @@ -402,47 +419,47 @@ static const struct a6xx_indexed_registers a6xx_indexed_reglist[] = { 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, + { "CP_SQE_UCODE_DBG", REG_A6XX_CP_SQE_UCODE_DBG_ADDR, REG_A6XX_CP_SQE_UCODE_DBG_DATA, 0x8000, NULL }, - { "CP_ROQ", REG_A6XX_CP_ROQ_DBG_ADDR, + { "CP_ROQ_DBG", REG_A6XX_CP_ROQ_DBG_ADDR, REG_A6XX_CP_ROQ_DBG_DATA, 0, a6xx_get_cp_roq_size}, }; static const struct a6xx_indexed_registers a7xx_indexed_reglist[] = { { "CP_SQE_STAT", REG_A6XX_CP_SQE_STAT_ADDR, - REG_A6XX_CP_SQE_STAT_DATA, 0x33, NULL }, + REG_A6XX_CP_SQE_STAT_DATA, 0x40, 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, + { "CP_SQE_UCODE_DBG", 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, + { "CP_BV_SQE_STAT", REG_A7XX_CP_BV_SQE_STAT_ADDR, + REG_A7XX_CP_BV_SQE_STAT_DATA, 0x40, NULL }, + { "CP_BV_DRAW_STATE", 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, + { "CP_BV_SQE_UCODE_DBG", 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, + { "CP_SQE_AC_STAT", REG_A7XX_CP_SQE_AC_STAT_ADDR, + REG_A7XX_CP_SQE_AC_STAT_DATA, 0x40, NULL }, + { "CP_LPAC_DRAW_STATE", 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, + { "CP_SQE_AC_UCODE_DBG", 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, + { "CP_LPAC_FIFO_DBG", REG_A7XX_CP_LPAC_FIFO_DBG_ADDR, REG_A7XX_CP_LPAC_FIFO_DBG_DATA, 0x40, NULL }, - { "CP_ROQ", REG_A6XX_CP_ROQ_DBG_ADDR, + { "CP_ROQ_DBG", REG_A6XX_CP_ROQ_DBG_ADDR, REG_A6XX_CP_ROQ_DBG_DATA, 0, a7xx_get_cp_roq_size }, }; static const struct a6xx_indexed_registers a6xx_cp_mempool_indexed = { - "CP_MEMPOOL", REG_A6XX_CP_MEM_POOL_DBG_ADDR, + "CP_MEM_POOL_DBG", REG_A6XX_CP_MEM_POOL_DBG_ADDR, REG_A6XX_CP_MEM_POOL_DBG_DATA, 0x2060, NULL, }; static const 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 }, + { "CP_MEM_POOL_DBG", REG_A6XX_CP_MEM_POOL_DBG_ADDR, + REG_A6XX_CP_MEM_POOL_DBG_DATA, 0x2200, NULL }, + { "CP_BV_MEM_POOL_DBG", REG_A7XX_CP_BV_MEM_POOL_DBG_ADDR, + REG_A7XX_CP_BV_MEM_POOL_DBG_DATA, 0x2200, NULL }, }; #define DEBUGBUS(_id, _count) { .id = _id, .name = #_id, .count = _count } @@ -558,7 +575,7 @@ struct gen7_sptp_cluster_registers { /* statetype: SP block state type for the cluster */ enum a7xx_statetype_id statetype; /* pipe_id: Pipe identifier */ - enum a7xx_pipe pipe_id; + enum adreno_pipe pipe_id; /* context_id: Context identifier */ int context_id; /* location_id: Location identifier */ @@ -784,10 +801,10 @@ static const char *a7xx_statetype_names[] = { }; static const char *a7xx_pipe_names[] = { - A7XX_NAME(A7XX_PIPE_NONE), - A7XX_NAME(A7XX_PIPE_BR), - A7XX_NAME(A7XX_PIPE_BV), - A7XX_NAME(A7XX_PIPE_LPAC), + A7XX_NAME(PIPE_NONE), + A7XX_NAME(PIPE_BR), + A7XX_NAME(PIPE_BV), + A7XX_NAME(PIPE_LPAC), }; static const char *a7xx_cluster_names[] = { diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c index cb8844ed46b2..53cfdf4e6c34 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c @@ -6,6 +6,7 @@ #include <linux/list.h> #include <soc/qcom/cmd-db.h> +#include <soc/qcom/tcs.h> #include "a6xx_gmu.h" #include "a6xx_gmu.xml.h" @@ -20,7 +21,9 @@ static const char * const a6xx_hfi_msg_id[] = { HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE), HFI_MSG_ID(HFI_H2F_MSG_TEST), HFI_MSG_ID(HFI_H2F_MSG_START), + HFI_MSG_ID(HFI_H2F_FEATURE_CTRL), HFI_MSG_ID(HFI_H2F_MSG_CORE_FW_START), + HFI_MSG_ID(HFI_H2F_MSG_TABLE), HFI_MSG_ID(HFI_H2F_MSG_GX_BW_PERF_VOTE), HFI_MSG_ID(HFI_H2F_MSG_PREPARE_SLUMBER), }; @@ -99,16 +102,29 @@ static int a6xx_hfi_queue_write(struct a6xx_gmu *gmu, return 0; } -static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum, - u32 *payload, u32 payload_size) +static int a6xx_hfi_wait_for_msg_interrupt(struct a6xx_gmu *gmu, u32 id, u32 seqnum) { - struct a6xx_hfi_queue *queue = &gmu->queues[HFI_RESPONSE_QUEUE]; - u32 val; int ret; + u32 val; + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); - /* Wait for a response */ - ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO, val, - val & A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ, 100, 5000); + do { + /* Wait for a response */ + ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO, val, + val & A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ, 100, 1000000); + + if (!ret) + break; + + if (completion_done(&a6xx_gpu->base.fault_coredump_done)) + break; + + /* We may timeout because the GMU is temporarily wedged from + * pending faults from the GPU and we are taking a devcoredump. + * Wait until the MMU is resumed and try again. + */ + wait_for_completion(&a6xx_gpu->base.fault_coredump_done); + } while (true); if (ret) { DRM_DEV_ERROR(gmu->dev, @@ -121,6 +137,19 @@ static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum, gmu_write(gmu, REG_A6XX_GMU_GMU2HOST_INTR_CLR, A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ); + return 0; +} + +static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum, + u32 *payload, u32 payload_size) +{ + struct a6xx_hfi_queue *queue = &gmu->queues[HFI_RESPONSE_QUEUE]; + int ret; + + ret = a6xx_hfi_wait_for_msg_interrupt(gmu, id, seqnum); + if (ret) + return ret; + for (;;) { struct a6xx_hfi_msg_response resp; @@ -128,12 +157,18 @@ static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum, ret = a6xx_hfi_queue_read(gmu, queue, (u32 *) &resp, sizeof(resp) >> 2); - /* If the queue is empty our response never made it */ + /* If the queue is empty, there may have been previous missed + * responses that preceded the response to our packet. Wait + * further before we give up. + */ if (!ret) { - DRM_DEV_ERROR(gmu->dev, - "The HFI response queue is unexpectedly empty\n"); - - return -ENOENT; + ret = a6xx_hfi_wait_for_msg_interrupt(gmu, id, seqnum); + if (ret) { + DRM_DEV_ERROR(gmu->dev, + "The HFI response queue is unexpectedly empty\n"); + return ret; + } + continue; } if (HFI_HEADER_ID(resp.header) == HFI_F2H_MSG_ERROR) { @@ -236,11 +271,63 @@ static int a6xx_hfi_send_perf_table_v1(struct a6xx_gmu *gmu) NULL, 0); } +static int a8xx_hfi_send_perf_table(struct a6xx_gmu *gmu) +{ + unsigned int num_gx_votes = 3, num_cx_votes = 2; + struct a6xx_hfi_table_entry *entry; + struct a6xx_hfi_table *tbl; + int ret, i; + u32 size; + + size = sizeof(*tbl) + (2 * sizeof(tbl->entry[0])) + + (gmu->nr_gpu_freqs * num_gx_votes * sizeof(gmu->gx_arc_votes[0])) + + (gmu->nr_gmu_freqs * num_cx_votes * sizeof(gmu->cx_arc_votes[0])); + tbl = kzalloc(size, GFP_KERNEL); + tbl->type = HFI_TABLE_GPU_PERF; + + /* First fill GX votes */ + entry = &tbl->entry[0]; + entry->count = gmu->nr_gpu_freqs; + entry->stride = num_gx_votes; + + for (i = 0; i < gmu->nr_gpu_freqs; i++) { + unsigned int base = i * entry->stride; + + entry->data[base+0] = gmu->gx_arc_votes[i]; + entry->data[base+1] = gmu->dep_arc_votes[i]; + entry->data[base+2] = gmu->gpu_freqs[i] / 1000; + } + + /* Then fill CX votes */ + entry = (struct a6xx_hfi_table_entry *) + &tbl->entry[0].data[gmu->nr_gpu_freqs * num_gx_votes]; + + entry->count = gmu->nr_gmu_freqs; + entry->stride = num_cx_votes; + + for (i = 0; i < gmu->nr_gmu_freqs; i++) { + unsigned int base = i * entry->stride; + + entry->data[base] = gmu->cx_arc_votes[i]; + entry->data[base+1] = gmu->gmu_freqs[i] / 1000; + } + + ret = a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_TABLE, tbl, size, NULL, 0); + + kfree(tbl); + return ret; +} + static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu) { + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; struct a6xx_hfi_msg_perf_table msg = { 0 }; int i; + if (adreno_is_a8xx(adreno_gpu)) + return a8xx_hfi_send_perf_table(gmu); + msg.num_gpu_levels = gmu->nr_gpu_freqs; msg.num_gmu_levels = gmu->nr_gmu_freqs; @@ -259,6 +346,48 @@ static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu) NULL, 0); } +static void a6xx_generate_bw_table(const struct a6xx_info *info, struct a6xx_gmu *gmu, + struct a6xx_hfi_msg_bw_table *msg) +{ + unsigned int i, j; + + for (i = 0; i < GMU_MAX_BCMS; i++) { + if (!info->bcms[i].name) + break; + msg->ddr_cmds_addrs[i] = cmd_db_read_addr(info->bcms[i].name); + } + msg->ddr_cmds_num = i; + + for (i = 0; i < gmu->nr_gpu_bws; ++i) + for (j = 0; j < msg->ddr_cmds_num; j++) + msg->ddr_cmds_data[i][j] = gmu->gpu_ib_votes[i][j]; + msg->bw_level_num = gmu->nr_gpu_bws; + + /* Compute the wait bitmask with each BCM having the commit bit */ + msg->ddr_wait_bitmask = 0; + for (j = 0; j < msg->ddr_cmds_num; j++) + if (msg->ddr_cmds_data[0][j] & BCM_TCS_CMD_COMMIT_MASK) + msg->ddr_wait_bitmask |= BIT(j); + + /* + * These are the CX (CNOC) votes - these are used by the GMU + * The 'CN0' BCM is used on all targets, and votes are basically + * 'off' and 'on' states with first bit to enable the path. + */ + + msg->cnoc_cmds_addrs[0] = cmd_db_read_addr("CN0"); + msg->cnoc_cmds_num = 1; + + msg->cnoc_cmds_data[0][0] = BCM_TCS_CMD(true, false, 0, 0); + msg->cnoc_cmds_data[1][0] = BCM_TCS_CMD(true, true, 0, BIT(0)); + + /* Compute the wait bitmask with each BCM having the commit bit */ + msg->cnoc_wait_bitmask = 0; + for (j = 0; j < msg->cnoc_cmds_num; j++) + if (msg->cnoc_cmds_data[0][j] & BCM_TCS_CMD_COMMIT_MASK) + msg->cnoc_wait_bitmask |= BIT(j); +} + static void a618_build_bw_table(struct a6xx_hfi_msg_bw_table *msg) { /* Send a single "off" entry since the 618 GMU doesn't do bus scaling */ @@ -664,6 +793,7 @@ static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu) struct a6xx_hfi_msg_bw_table *msg; struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + const struct a6xx_info *info = adreno_gpu->info->a6xx; if (gmu->bw_table) goto send; @@ -672,7 +802,9 @@ static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu) if (!msg) return -ENOMEM; - if (adreno_is_a618(adreno_gpu)) + if (info->bcms && gmu->nr_gpu_bws > 1) + a6xx_generate_bw_table(info, gmu, msg); + else if (adreno_is_a618(adreno_gpu)) a618_build_bw_table(msg); else if (adreno_is_a619(adreno_gpu)) a619_build_bw_table(msg); @@ -702,6 +834,55 @@ send: NULL, 0); } +static int a6xx_hfi_feature_ctrl_msg(struct a6xx_gmu *gmu, u32 feature, u32 enable, u32 data) +{ + struct a6xx_hfi_msg_feature_ctrl msg = { + .feature = feature, + .enable = enable, + .data = data, + }; + + return a6xx_hfi_send_msg(gmu, HFI_H2F_FEATURE_CTRL, &msg, sizeof(msg), NULL, 0); +} + +#define HFI_FEATURE_IFPC 9 +#define IFPC_LONG_HYST 0x1680 + +static int a6xx_hfi_enable_ifpc(struct a6xx_gmu *gmu) +{ + if (gmu->idle_level != GMU_IDLE_STATE_IFPC) + return 0; + + return a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_IFPC, 1, IFPC_LONG_HYST); +} + +#define HFI_FEATURE_ACD 12 + +static int a6xx_hfi_enable_acd(struct a6xx_gmu *gmu) +{ + struct a6xx_hfi_acd_table *acd_table = &gmu->acd_table; + int ret; + + if (!acd_table->enable_by_level) + return 0; + + /* Enable ACD feature at GMU */ + ret = a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_ACD, 1, 0); + if (ret) { + DRM_DEV_ERROR(gmu->dev, "Unable to enable ACD (%d)\n", ret); + return ret; + } + + /* Send ACD table to GMU */ + ret = a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_ACD, acd_table, sizeof(*acd_table), NULL, 0); + if (ret) { + DRM_DEV_ERROR(gmu->dev, "Unable to ACD table (%d)\n", ret); + return ret; + } + + return 0; +} + static int a6xx_hfi_send_test(struct a6xx_gmu *gmu) { struct a6xx_hfi_msg_test msg = { 0 }; @@ -726,13 +907,13 @@ static int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu) sizeof(msg), NULL, 0); } -int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index) +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, u32 freq_index, u32 bw_index) { struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 }; msg.ack_type = 1; /* blocking */ - msg.freq = index; - msg.bw = 0; /* TODO: bus scaling */ + msg.freq = freq_index; + msg.bw = bw_index; return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg, sizeof(msg), NULL, 0); @@ -799,6 +980,14 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state) if (ret) return ret; + ret = a6xx_hfi_enable_acd(gmu); + if (ret) + return ret; + + ret = a6xx_hfi_enable_ifpc(gmu); + if (ret) + return ret; + ret = a6xx_hfi_send_core_fw_start(gmu); if (ret) return ret; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h index 528110169398..6f9f74a0bc85 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h @@ -151,12 +151,33 @@ struct a6xx_hfi_msg_test { u32 header; }; +#define HFI_H2F_MSG_ACD 7 +#define MAX_ACD_STRIDE 2 + +struct a6xx_hfi_acd_table { + u32 header; + u32 version; + u32 enable_by_level; + u32 stride; + u32 num_levels; + u32 data[16 * MAX_ACD_STRIDE]; +}; + #define HFI_H2F_MSG_START 10 struct a6xx_hfi_msg_start { u32 header; }; +#define HFI_H2F_FEATURE_CTRL 11 + +struct a6xx_hfi_msg_feature_ctrl { + u32 header; + u32 feature; + u32 enable; + u32 data; +}; + #define HFI_H2F_MSG_CORE_FW_START 14 struct a6xx_hfi_msg_core_fw_start { @@ -164,6 +185,23 @@ struct a6xx_hfi_msg_core_fw_start { u32 handle; }; +#define HFI_H2F_MSG_TABLE 15 + +struct a6xx_hfi_table_entry { + u32 count; + u32 stride; + u32 data[]; +}; + +struct a6xx_hfi_table { + u32 header; + u32 version; + u32 type; +#define HFI_TABLE_BW_VOTE 0 +#define HFI_TABLE_GPU_PERF 1 + struct a6xx_hfi_table_entry entry[]; +}; + #define HFI_H2F_MSG_GX_BW_PERF_VOTE 30 struct a6xx_hfi_gx_bw_perf_vote_cmd { @@ -173,6 +211,11 @@ struct a6xx_hfi_gx_bw_perf_vote_cmd { u32 bw; }; +#define AB_VOTE_MASK GENMASK(31, 16) +#define MAX_AB_VOTE (FIELD_MAX(AB_VOTE_MASK) - 1) +#define AB_VOTE(vote) FIELD_PREP(AB_VOTE_MASK, (vote)) +#define AB_VOTE_ENABLE BIT(8) + #define HFI_H2F_MSG_PREPARE_SLUMBER 33 struct a6xx_hfi_prep_slumber_cmd { diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c index 2fd4e39f618f..afc5f4aa3b17 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c @@ -41,7 +41,7 @@ static inline void set_preempt_state(struct a6xx_gpu *gpu, } /* Write the most recent wptr for the given ring into the hardware */ -static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +static inline void update_wptr(struct a6xx_gpu *a6xx_gpu, struct msm_ringbuffer *ring) { unsigned long flags; uint32_t wptr; @@ -51,7 +51,7 @@ static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) if (ring->restore_wptr) { wptr = get_wptr(ring); - gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr); + a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false); ring->restore_wptr = false; } @@ -87,7 +87,8 @@ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu) static void a6xx_preempt_timer(struct timer_list *t) { - struct a6xx_gpu *a6xx_gpu = from_timer(a6xx_gpu, t, preempt_timer); + struct a6xx_gpu *a6xx_gpu = timer_container_of(a6xx_gpu, t, + preempt_timer); struct msm_gpu *gpu = &a6xx_gpu->base.base; struct drm_device *dev = gpu->dev; @@ -110,9 +111,9 @@ static void preempt_prepare_postamble(struct a6xx_gpu *a6xx_gpu) postamble[count++] = PKT7(CP_WAIT_REG_MEM, 6); postamble[count++] = CP_WAIT_REG_MEM_0_FUNCTION(WRITE_EQ); - postamble[count++] = CP_WAIT_REG_MEM_1_POLL_ADDR_LO( + postamble[count++] = CP_WAIT_REG_MEM_POLL_ADDR_LO( REG_A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS); - postamble[count++] = CP_WAIT_REG_MEM_2_POLL_ADDR_HI(0); + postamble[count++] = CP_WAIT_REG_MEM_POLL_ADDR_HI(0); postamble[count++] = CP_WAIT_REG_MEM_3_REF(0x1); postamble[count++] = CP_WAIT_REG_MEM_4_MASK(0x1); postamble[count++] = CP_WAIT_REG_MEM_5_DELAY_LOOP_CYCLES(0); @@ -135,6 +136,21 @@ static void preempt_disable_postamble(struct a6xx_gpu *a6xx_gpu) a6xx_gpu->postamble_enabled = false; } +/* + * Set preemption keepalive vote. Please note that this vote is different from the one used in + * a6xx_irq() + */ +static void a6xx_preempt_keepalive_vote(struct msm_gpu *gpu, bool on) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + + if (adreno_has_gmu_wrapper(adreno_gpu)) + return; + + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_PWR_COL_PREEMPT_KEEPALIVE, on); +} + void a6xx_preempt_irq(struct msm_gpu *gpu) { uint32_t status; @@ -146,7 +162,7 @@ void a6xx_preempt_irq(struct msm_gpu *gpu) return; /* Delete the preemption watchdog timer */ - del_timer(&a6xx_gpu->preempt_timer); + timer_delete(&a6xx_gpu->preempt_timer); /* * The hardware should be setting the stop bit of CP_CONTEXT_SWITCH_CNTL @@ -171,10 +187,12 @@ void a6xx_preempt_irq(struct msm_gpu *gpu) set_preempt_state(a6xx_gpu, PREEMPT_FINISH); - update_wptr(gpu, a6xx_gpu->cur_ring); + update_wptr(a6xx_gpu, a6xx_gpu->cur_ring); set_preempt_state(a6xx_gpu, PREEMPT_NONE); + a6xx_preempt_keepalive_vote(gpu, false); + trace_msm_gpu_preemption_irq(a6xx_gpu->cur_ring->id); /* @@ -209,7 +227,7 @@ void a6xx_preempt_hw_init(struct msm_gpu *gpu) gpu_write64(gpu, REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, 0); /* Enable the GMEM save/restore feature for preemption */ - gpu_write(gpu, REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE, 0x1); + gpu_write(gpu, REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE, 0x1); /* Reset the preemption state */ set_preempt_state(a6xx_gpu, PREEMPT_NONE); @@ -267,7 +285,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu) */ if (!ring || (a6xx_gpu->cur_ring == ring)) { set_preempt_state(a6xx_gpu, PREEMPT_FINISH); - update_wptr(gpu, a6xx_gpu->cur_ring); + update_wptr(a6xx_gpu, a6xx_gpu->cur_ring); set_preempt_state(a6xx_gpu, PREEMPT_NONE); spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags); return; @@ -301,13 +319,16 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu) spin_unlock_irqrestore(&ring->preempt_lock, flags); - gpu_write64(gpu, - REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, - a6xx_gpu->preempt_smmu_iova[ring->id]); + /* Set the keepalive bit to keep the GPU ON until preemption is complete */ + a6xx_preempt_keepalive_vote(gpu, true); + + a6xx_fenced_write(a6xx_gpu, + REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, a6xx_gpu->preempt_smmu_iova[ring->id], + BIT(1), true); - gpu_write64(gpu, + a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR, - a6xx_gpu->preempt_iova[ring->id]); + a6xx_gpu->preempt_iova[ring->id], BIT(1), true); a6xx_gpu->next_ring = ring; @@ -327,7 +348,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu) set_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED); /* Trigger the preemption */ - gpu_write(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl); + a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl, BIT(1), false); } static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu, @@ -343,7 +364,7 @@ static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu, ptr = msm_gem_kernel_new(gpu->dev, PREEMPT_RECORD_SIZE(adreno_gpu), - MSM_BO_WC | MSM_BO_MAP_PRIV, gpu->aspace, &bo, &iova); + MSM_BO_WC | MSM_BO_MAP_PRIV, gpu->vm, &bo, &iova); if (IS_ERR(ptr)) return PTR_ERR(ptr); @@ -361,7 +382,7 @@ static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu, ptr = msm_gem_kernel_new(gpu->dev, PREEMPT_SMMU_INFO_SIZE, MSM_BO_WC | MSM_BO_MAP_PRIV | MSM_BO_GPU_READONLY, - gpu->aspace, &bo, &iova); + gpu->vm, &bo, &iova); if (IS_ERR(ptr)) return PTR_ERR(ptr); @@ -376,7 +397,7 @@ static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu, struct a7xx_cp_smmu_info *smmu_info_ptr = ptr; - msm_iommu_pagetable_params(gpu->aspace->mmu, &ttbr, &asid); + msm_iommu_pagetable_params(to_msm_vm(gpu->vm)->mmu, &ttbr, &asid); smmu_info_ptr->magic = GEN7_CP_SMMU_INFO_MAGIC; smmu_info_ptr->ttbr0 = ttbr; @@ -404,7 +425,7 @@ void a6xx_preempt_fini(struct msm_gpu *gpu) int i; for (i = 0; i < gpu->nr_rings; i++) - msm_gem_kernel_put(a6xx_gpu->preempt_bo[i], gpu->aspace); + msm_gem_kernel_put(a6xx_gpu->preempt_bo[i], gpu->vm); } void a6xx_preempt_init(struct msm_gpu *gpu) @@ -430,7 +451,7 @@ void a6xx_preempt_init(struct msm_gpu *gpu) a6xx_gpu->preempt_postamble_ptr = msm_gem_kernel_new(gpu->dev, PAGE_SIZE, MSM_BO_WC | MSM_BO_MAP_PRIV | MSM_BO_GPU_READONLY, - gpu->aspace, &a6xx_gpu->preempt_postamble_bo, + gpu->vm, &a6xx_gpu->preempt_postamble_bo, &a6xx_gpu->preempt_postamble_iova); preempt_prepare_postamble(a6xx_gpu); diff --git a/drivers/gpu/drm/msm/adreno/a8xx_gpu.c b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c new file mode 100644 index 000000000000..30de078e9dfd --- /dev/null +++ b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c @@ -0,0 +1,1201 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ + + +#include "msm_gem.h" +#include "msm_mmu.h" +#include "msm_gpu_trace.h" +#include "a6xx_gpu.h" +#include "a6xx_gmu.xml.h" + +#include <linux/bitfield.h> +#include <linux/devfreq.h> +#include <linux/firmware/qcom/qcom_scm.h> +#include <linux/pm_domain.h> +#include <linux/soc/qcom/llcc-qcom.h> + +#define GPU_PAS_ID 13 + +static void a8xx_aperture_slice_set(struct msm_gpu *gpu, enum adreno_pipe pipe, u32 slice) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + u32 val; + + val = A8XX_CP_APERTURE_CNTL_HOST_PIPEID(pipe) | A8XX_CP_APERTURE_CNTL_HOST_SLICEID(slice); + + if (a6xx_gpu->cached_aperture == val) + return; + + gpu_write(gpu, REG_A8XX_CP_APERTURE_CNTL_HOST, val); + + a6xx_gpu->cached_aperture = val; +} + +static void a8xx_aperture_acquire(struct msm_gpu *gpu, enum adreno_pipe pipe, unsigned long *flags) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + + spin_lock_irqsave(&a6xx_gpu->aperture_lock, *flags); + + a8xx_aperture_slice_set(gpu, pipe, 0); +} + +static void a8xx_aperture_release(struct msm_gpu *gpu, unsigned long flags) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + + spin_unlock_irqrestore(&a6xx_gpu->aperture_lock, flags); +} + +static void a8xx_aperture_clear(struct msm_gpu *gpu) +{ + unsigned long flags; + + a8xx_aperture_acquire(gpu, PIPE_NONE, &flags); + a8xx_aperture_release(gpu, flags); +} + +static void a8xx_write_pipe(struct msm_gpu *gpu, enum adreno_pipe pipe, u32 offset, u32 data) +{ + unsigned long flags; + + a8xx_aperture_acquire(gpu, pipe, &flags); + gpu_write(gpu, offset, data); + a8xx_aperture_release(gpu, flags); +} + +static u32 a8xx_read_pipe_slice(struct msm_gpu *gpu, enum adreno_pipe pipe, u32 slice, u32 offset) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + unsigned long flags; + u32 val; + + spin_lock_irqsave(&a6xx_gpu->aperture_lock, flags); + a8xx_aperture_slice_set(gpu, pipe, slice); + val = gpu_read(gpu, offset); + spin_unlock_irqrestore(&a6xx_gpu->aperture_lock, flags); + + return val; +} + +void a8xx_gpu_get_slice_info(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + const struct a6xx_info *info = adreno_gpu->info->a6xx; + u32 slice_mask; + + if (adreno_gpu->info->family < ADRENO_8XX_GEN1) + return; + + if (a6xx_gpu->slice_mask) + return; + + slice_mask = GENMASK(info->max_slices - 1, 0); + + /* GEN1 doesn't support partial slice configurations */ + if (adreno_gpu->info->family == ADRENO_8XX_GEN1) { + a6xx_gpu->slice_mask = slice_mask; + return; + } + + slice_mask &= a6xx_llc_read(a6xx_gpu, + REG_A8XX_CX_MISC_SLICE_ENABLE_FINAL); + + a6xx_gpu->slice_mask = slice_mask; + + /* Chip ID depends on the number of slices available. So update it */ + adreno_gpu->chip_id |= FIELD_PREP(GENMASK(7, 4), hweight32(slice_mask)); +} + +static u32 a8xx_get_first_slice(struct a6xx_gpu *a6xx_gpu) +{ + return ffs(a6xx_gpu->slice_mask) - 1; +} + +static inline bool _a8xx_check_idle(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + + /* Check that the GMU is idle */ + if (!a6xx_gmu_isidle(&a6xx_gpu->gmu)) + return false; + + /* Check that the CX master is idle */ + if (gpu_read(gpu, REG_A8XX_RBBM_STATUS) & + ~A8XX_RBBM_STATUS_CP_AHB_BUSY_CX_MASTER) + return false; + + return !(gpu_read(gpu, REG_A8XX_RBBM_INT_0_STATUS) & + A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT); +} + +static bool a8xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +{ + /* wait for CP to drain ringbuffer: */ + if (!adreno_idle(gpu, ring)) + return false; + + if (spin_until(_a8xx_check_idle(gpu))) { + DRM_ERROR( + "%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X rptr/wptr %d/%d\n", + gpu->name, __builtin_return_address(0), + gpu_read(gpu, REG_A8XX_RBBM_STATUS), + gpu_read(gpu, REG_A8XX_RBBM_INT_0_STATUS), + gpu_read(gpu, REG_A6XX_CP_RB_RPTR), + gpu_read(gpu, REG_A6XX_CP_RB_WPTR)); + return false; + } + + return true; +} + +void a8xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + uint32_t wptr; + unsigned long flags; + + spin_lock_irqsave(&ring->preempt_lock, flags); + + /* Copy the shadow to the actual register */ + ring->cur = ring->next; + + /* Make sure to wrap wptr if we need to */ + wptr = get_wptr(ring); + + /* Update HW if this is the current ring and we are not in preempt*/ + if (!a6xx_in_preempt(a6xx_gpu)) { + if (a6xx_gpu->cur_ring == ring) + gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr); + else + ring->restore_wptr = true; + } else { + ring->restore_wptr = true; + } + + spin_unlock_irqrestore(&ring->preempt_lock, flags); +} + +static void a8xx_set_hwcg(struct msm_gpu *gpu, bool state) +{ + 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; + u32 val; + + if (adreno_is_x285(adreno_gpu) && state) + gpu_write(gpu, REG_A8XX_RBBM_CGC_0_PC, 0x00000702); + + gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL, + state ? adreno_gpu->info->a6xx->gmu_cgc_mode : 0); + gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL, + state ? 0x110111 : 0); + gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL, + state ? 0x55555 : 0); + + gpu_write(gpu, REG_A8XX_RBBM_CLOCK_CNTL_GLOBAL, 1); + gpu_write(gpu, REG_A8XX_RBBM_CGC_GLOBAL_LOAD_CMD, !!state); + + if (state) { + gpu_write(gpu, REG_A8XX_RBBM_CGC_P2S_TRIG_CMD, 1); + + if (gpu_poll_timeout(gpu, REG_A8XX_RBBM_CGC_P2S_STATUS, val, + val & A8XX_RBBM_CGC_P2S_STATUS_TXDONE, 1, 10)) { + dev_err(&gpu->pdev->dev, "RBBM_CGC_P2S_STATUS TXDONE Poll failed\n"); + return; + } + + gpu_write(gpu, REG_A8XX_RBBM_CLOCK_CNTL_GLOBAL, 0); + } else { + /* + * GMU enables clk gating in GBIF during boot up. So, + * override that here when hwcg feature is disabled + */ + gpu_rmw(gpu, REG_A8XX_GBIF_CX_CONFIG, BIT(0), 0); + } +} + +static void a8xx_set_cp_protect(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + const struct adreno_protect *protect = adreno_gpu->info->a6xx->protect; + u32 cntl, final_cfg; + unsigned int i; + + cntl = A8XX_CP_PROTECT_CNTL_PIPE_ACCESS_PROT_EN | + A8XX_CP_PROTECT_CNTL_PIPE_ACCESS_FAULT_ON_VIOL_EN | + A8XX_CP_PROTECT_CNTL_PIPE_LAST_SPAN_INF_RANGE | + A8XX_CP_PROTECT_CNTL_PIPE_HALT_SQE_RANGE__MASK; + /* + * Enable access protection to privileged registers, fault on an access + * protect violation and select the last span to protect from the start + * address all the way to the end of the register address space + */ + a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_CP_PROTECT_CNTL_PIPE, cntl); + a8xx_write_pipe(gpu, PIPE_BV, REG_A8XX_CP_PROTECT_CNTL_PIPE, cntl); + + a8xx_aperture_clear(gpu); + + for (i = 0; i < protect->count; i++) { + /* Intentionally skip writing to some registers */ + if (protect->regs[i]) { + gpu_write(gpu, REG_A8XX_CP_PROTECT_GLOBAL(i), protect->regs[i]); + final_cfg = protect->regs[i]; + } + } + + /* + * Last span feature is only supported on PIPE specific register. + * So update those here + */ + a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_CP_PROTECT_PIPE(protect->count_max), final_cfg); + a8xx_write_pipe(gpu, PIPE_BV, REG_A8XX_CP_PROTECT_PIPE(protect->count_max), final_cfg); + + a8xx_aperture_clear(gpu); +} + +static void a8xx_set_ubwc_config(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + const struct qcom_ubwc_cfg_data *cfg = adreno_gpu->ubwc_config; + u32 level2_swizzling_dis = !(cfg->ubwc_swizzle & UBWC_SWIZZLE_ENABLE_LVL2); + u32 level3_swizzling_dis = !(cfg->ubwc_swizzle & UBWC_SWIZZLE_ENABLE_LVL3); + bool rgba8888_lossless = false, fp16compoptdis = false; + bool yuvnotcomptofc = false, min_acc_len_64b = false; + bool rgb565_predicator = false, amsbc = false; + bool ubwc_mode = qcom_ubwc_get_ubwc_mode(cfg); + u32 ubwc_version = cfg->ubwc_enc_version; + u32 hbb, hbb_hi, hbb_lo, mode = 1; + u8 uavflagprd_inv = 2; + + switch (ubwc_version) { + case UBWC_5_0: + amsbc = true; + rgb565_predicator = true; + mode = 4; + break; + case UBWC_4_0: + amsbc = true; + rgb565_predicator = true; + fp16compoptdis = true; + rgba8888_lossless = true; + mode = 2; + break; + case UBWC_3_0: + amsbc = true; + mode = 1; + break; + default: + dev_err(&gpu->pdev->dev, "Unknown UBWC version: 0x%x\n", ubwc_version); + break; + } + + /* + * We subtract 13 from the highest bank bit (13 is the minimum value + * allowed by hw) and write the lowest two bits of the remaining value + * as hbb_lo and the one above it as hbb_hi to the hardware. + */ + WARN_ON(cfg->highest_bank_bit < 13); + hbb = cfg->highest_bank_bit - 13; + hbb_hi = hbb >> 2; + hbb_lo = hbb & 3; + a8xx_write_pipe(gpu, PIPE_BV, REG_A8XX_GRAS_NC_MODE_CNTL, hbb << 5); + a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_GRAS_NC_MODE_CNTL, hbb << 5); + + a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_RB_CCU_NC_MODE_CNTL, + yuvnotcomptofc << 6 | + hbb_hi << 3 | + hbb_lo << 1); + + a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_RB_CMP_NC_MODE_CNTL, + mode << 15 | + yuvnotcomptofc << 6 | + rgba8888_lossless << 4 | + fp16compoptdis << 3 | + rgb565_predicator << 2 | + amsbc << 1 | + min_acc_len_64b); + + a8xx_aperture_clear(gpu); + + gpu_write(gpu, REG_A6XX_SP_NC_MODE_CNTL, + level3_swizzling_dis << 13 | + level2_swizzling_dis << 12 | + hbb_hi << 10 | + uavflagprd_inv << 4 | + min_acc_len_64b << 3 | + hbb_lo << 1 | ubwc_mode); + + gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, + level3_swizzling_dis << 7 | + level2_swizzling_dis << 6 | + hbb_hi << 4 | + min_acc_len_64b << 3 | + hbb_lo << 1 | ubwc_mode); +} + +static void a8xx_nonctxt_config(struct msm_gpu *gpu, u32 *gmem_protect) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + const struct a6xx_info *info = adreno_gpu->info->a6xx; + const struct adreno_reglist_pipe *regs = info->nonctxt_reglist; + unsigned int pipe_id, i; + unsigned long flags; + + for (pipe_id = PIPE_NONE; pipe_id <= PIPE_DDE_BV; pipe_id++) { + /* We don't have support for LPAC yet */ + if (pipe_id == PIPE_LPAC) + continue; + + a8xx_aperture_acquire(gpu, pipe_id, &flags); + + for (i = 0; regs[i].offset; i++) { + if (!(BIT(pipe_id) & regs[i].pipe)) + continue; + + if (regs[i].offset == REG_A8XX_RB_GC_GMEM_PROTECT) + *gmem_protect = regs[i].value; + + gpu_write(gpu, regs[i].offset, regs[i].value); + } + + a8xx_aperture_release(gpu, flags); + } + + a8xx_aperture_clear(gpu); +} + +static int a8xx_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, 4); + + /* 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); + + 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); + + a6xx_flush(gpu, ring); + return a8xx_idle(gpu, ring) ? 0 : -EINVAL; +} + +#define A8XX_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 | \ + A6XX_RBBM_INT_0_MASK_SWFUSEVIOLATION) + +#define A8XX_APRIV_MASK \ + (A8XX_CP_APRIV_CNTL_PIPE_ICACHE | \ + A8XX_CP_APRIV_CNTL_PIPE_RBFETCH | \ + A8XX_CP_APRIV_CNTL_PIPE_RBPRIVLEVEL | \ + A8XX_CP_APRIV_CNTL_PIPE_RBRPWB) + +#define A8XX_BR_APRIV_MASK \ + (A8XX_APRIV_MASK | \ + A8XX_CP_APRIV_CNTL_PIPE_CDREAD | \ + A8XX_CP_APRIV_CNTL_PIPE_CDWRITE) + +#define A8XX_CP_GLOBAL_INT_MASK \ + (A8XX_CP_GLOBAL_INT_MASK_HWFAULTBR | \ + A8XX_CP_GLOBAL_INT_MASK_HWFAULTBV | \ + A8XX_CP_GLOBAL_INT_MASK_HWFAULTLPAC | \ + A8XX_CP_GLOBAL_INT_MASK_HWFAULTAQE0 | \ + A8XX_CP_GLOBAL_INT_MASK_HWFAULTAQE1 | \ + A8XX_CP_GLOBAL_INT_MASK_HWFAULTDDEBR | \ + A8XX_CP_GLOBAL_INT_MASK_HWFAULTDDEBV | \ + A8XX_CP_GLOBAL_INT_MASK_SWFAULTBR | \ + A8XX_CP_GLOBAL_INT_MASK_SWFAULTBV | \ + A8XX_CP_GLOBAL_INT_MASK_SWFAULTLPAC | \ + A8XX_CP_GLOBAL_INT_MASK_SWFAULTAQE0 | \ + A8XX_CP_GLOBAL_INT_MASK_SWFAULTAQE1 | \ + A8XX_CP_GLOBAL_INT_MASK_SWFAULTDDEBR | \ + A8XX_CP_GLOBAL_INT_MASK_SWFAULTDDEBV) + +#define A8XX_CP_INTERRUPT_STATUS_MASK_PIPE \ + (A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_CSFRBWRAP | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_CSFIB1WRAP | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_CSFIB2WRAP | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_CSFIB3WRAP | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_CSFSDSWRAP | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_CSFMRBWRAP | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_CSFVSDWRAP | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_OPCODEERROR | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_VSDPARITYERROR | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_REGISTERPROTECTIONERROR | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_ILLEGALINSTRUCTION | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_SMMUFAULT | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_VBIFRESPCLIENT| \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_VBIFRESPTYPE | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_VBIFRESPREAD | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_VBIFRESP | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_RTWROVF | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_LRZRTWROVF | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_LRZRTREFCNTOVF | \ + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_LRZRTCLRRESMISS) + +#define A8XX_CP_HW_FAULT_STATUS_MASK_PIPE \ + (A8XX_CP_HW_FAULT_STATUS_MASK_PIPE_CSFRBFAULT | \ + A8XX_CP_HW_FAULT_STATUS_MASK_PIPE_CSFIB1FAULT | \ + A8XX_CP_HW_FAULT_STATUS_MASK_PIPE_CSFIB2FAULT | \ + A8XX_CP_HW_FAULT_STATUS_MASK_PIPE_CSFIB3FAULT | \ + A8XX_CP_HW_FAULT_STATUS_MASK_PIPE_CSFSDSFAULT | \ + A8XX_CP_HW_FAULT_STATUS_MASK_PIPE_CSFMRBFAULT | \ + A8XX_CP_HW_FAULT_STATUS_MASK_PIPE_CSFVSDFAULT | \ + A8XX_CP_HW_FAULT_STATUS_MASK_PIPE_SQEREADBURSTOVF | \ + A8XX_CP_HW_FAULT_STATUS_MASK_PIPE_EVENTENGINEOVF | \ + A8XX_CP_HW_FAULT_STATUS_MASK_PIPE_UCODEERROR) + +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; + unsigned int pipe_id, i; + u32 gmem_protect = 0; + u64 gmem_range_min; + int ret; + + ret = a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); + if (ret) + return ret; + + /* Clear the cached value to force aperture configuration next time */ + a6xx_gpu->cached_aperture = UINT_MAX; + a8xx_aperture_clear(gpu); + + /* Clear GBIF halt in case GX domain was not collapsed */ + gpu_write(gpu, REG_A6XX_GBIF_HALT, 0); + gpu_read(gpu, REG_A6XX_GBIF_HALT); + + gpu_write(gpu, REG_A8XX_RBBM_GBIF_HALT, 0); + gpu_read(gpu, REG_A8XX_RBBM_GBIF_HALT); + + gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_CNTL, 0); + + /* + * Disable the trusted memory range - we don't actually supported secure + * memory rendering at this point in time and we don't want to block off + * part of the virtual memory space. + */ + gpu_write64(gpu, REG_A6XX_RBBM_SECVID_TSB_TRUSTED_BASE, 0x00000000); + gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000); + + /* Make all blocks contribute to the GPU BUSY perf counter */ + gpu_write(gpu, REG_A8XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xffffffff); + + /* Setup GMEM Range in UCHE */ + gmem_range_min = SZ_64M; + /* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */ + gpu_write64(gpu, REG_A8XX_UCHE_CCHE_GC_GMEM_RANGE_MIN, gmem_range_min); + gpu_write64(gpu, REG_A8XX_SP_HLSQ_GC_GMEM_RANGE_MIN, gmem_range_min); + + /* Setup UCHE Trap region */ + gpu_write64(gpu, REG_A8XX_UCHE_TRAP_BASE, adreno_gpu->uche_trap_base); + gpu_write64(gpu, REG_A8XX_UCHE_WRITE_THRU_BASE, adreno_gpu->uche_trap_base); + gpu_write64(gpu, REG_A8XX_UCHE_CCHE_TRAP_BASE, adreno_gpu->uche_trap_base); + gpu_write64(gpu, REG_A8XX_UCHE_CCHE_WRITE_THRU_BASE, adreno_gpu->uche_trap_base); + + /* Turn on performance counters */ + gpu_write(gpu, REG_A8XX_RBBM_PERFCTR_CNTL, 0x1); + gpu_write(gpu, REG_A8XX_RBBM_SLICE_PERFCTR_CNTL, 0x1); + + /* Turn on the IFPC counter (countable 4 on XOCLK1) */ + gmu_write(&a6xx_gpu->gmu, REG_A8XX_GMU_CX_GMU_POWER_COUNTER_SELECT_XOCLK_1, + FIELD_PREP(GENMASK(7, 0), 0x4)); + + /* Select CP0 to always count cycles */ + gpu_write(gpu, REG_A8XX_CP_PERFCTR_CP_SEL(0), 1); + + a8xx_set_ubwc_config(gpu); + + /* Set weights for bicubic filtering */ + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(0), 0); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(1), 0x3fe05ff4); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(2), 0x3fa0ebee); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(3), 0x3f5193ed); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(4), 0x3f0243f0); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(5), 0x00000000); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(6), 0x3fd093e8); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(7), 0x3f4133dc); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(8), 0x3ea1dfdb); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(9), 0x3e0283e0); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(10), 0x0000ac2b); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(11), 0x0000f01d); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(12), 0x00114412); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(13), 0x0021980a); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(14), 0x0051ec05); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(15), 0x0000380e); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(16), 0x3ff09001); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(17), 0x3fc10bfa); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(18), 0x3f9193f7); + gpu_write(gpu, REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(19), 0x3f7227f7); + + gpu_write(gpu, REG_A8XX_UCHE_CLIENT_PF, BIT(7) | 0x1); + + a8xx_nonctxt_config(gpu, &gmem_protect); + + /* Enable fault detection */ + gpu_write(gpu, REG_A8XX_RBBM_INTERFACE_HANG_INT_CNTL, BIT(30) | 0xcfffff); + gpu_write(gpu, REG_A8XX_RBBM_SLICE_INTERFACE_HANG_INT_CNTL, BIT(30)); + + /* Set up the CX GMU counter 0 to count busy ticks */ + gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000); + + /* Enable the power counter */ + gmu_rmw(gmu, REG_A8XX_GMU_CX_GMU_POWER_COUNTER_SELECT_XOCLK_0, 0xff, BIT(5)); + gmu_write(gmu, REG_A8XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1); + + /* Protect registers from the CP */ + a8xx_set_cp_protect(gpu); + + /* Enable the GMEM save/restore feature for preemption */ + a8xx_write_pipe(gpu, PIPE_BR, REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE, 1); + + for (pipe_id = PIPE_BR; pipe_id <= PIPE_DDE_BV; pipe_id++) { + u32 apriv_mask = A8XX_APRIV_MASK; + unsigned long flags; + + if (pipe_id == PIPE_LPAC) + continue; + + if (pipe_id == PIPE_BR) + apriv_mask = A8XX_BR_APRIV_MASK; + + a8xx_aperture_acquire(gpu, pipe_id, &flags); + gpu_write(gpu, REG_A8XX_CP_APRIV_CNTL_PIPE, apriv_mask); + gpu_write(gpu, REG_A8XX_CP_INTERRUPT_STATUS_MASK_PIPE, + A8XX_CP_INTERRUPT_STATUS_MASK_PIPE); + gpu_write(gpu, REG_A8XX_CP_HW_FAULT_STATUS_MASK_PIPE, + A8XX_CP_HW_FAULT_STATUS_MASK_PIPE); + a8xx_aperture_release(gpu, flags); + } + + a8xx_aperture_clear(gpu); + + /* Enable interrupts */ + gpu_write(gpu, REG_A8XX_CP_INTERRUPT_STATUS_MASK_GLOBAL, A8XX_CP_GLOBAL_INT_MASK); + gpu_write(gpu, REG_A8XX_RBBM_INT_0_MASK, A8XX_INT_MASK); + + ret = adreno_hw_init(gpu); + if (ret) + goto out; + + gpu_write64(gpu, REG_A8XX_CP_SQE_INSTR_BASE, a6xx_gpu->sqe_iova); + if (a6xx_gpu->aqe_iova) + gpu_write64(gpu, REG_A8XX_CP_AQE_INSTR_BASE_0, a6xx_gpu->aqe_iova); + + /* Set the ringbuffer address */ + gpu_write64(gpu, REG_A6XX_CP_RB_BASE, gpu->rb[0]->iova); + gpu_write(gpu, REG_A6XX_CP_RB_CNTL, MSM_GPU_RB_CNTL_DEFAULT); + + /* Configure the RPTR shadow if needed: */ + gpu_write64(gpu, REG_A6XX_CP_RB_RPTR_ADDR, shadowptr(a6xx_gpu, gpu->rb[0])); + gpu_write64(gpu, REG_A8XX_CP_RB_RPTR_ADDR_BV, rbmemptr(gpu->rb[0], bv_rptr)); + + for (i = 0; i < gpu->nr_rings; i++) + a6xx_gpu->shadow[i] = 0; + + /* Always come up on rb 0 */ + a6xx_gpu->cur_ring = gpu->rb[0]; + + for (i = 0; i < gpu->nr_rings; i++) + gpu->rb[i]->cur_ctx_seqno = 0; + + /* Enable the SQE_to start the CP engine */ + gpu_write(gpu, REG_A8XX_CP_SQE_CNTL, 1); + + ret = a8xx_cp_init(gpu); + if (ret) + goto out; + + /* + * Try to load a zap shader into the secure world. If successful + * we can use the CP to switch out of secure mode. If not then we + * have no resource but to try to switch ourselves out manually. If we + * guessed wrong then access to the RBBM_SECVID_TRUST_CNTL register will + * be blocked and a permissions violation will soon follow. + */ + ret = a6xx_zap_shader_init(gpu); + if (!ret) { + OUT_PKT7(gpu->rb[0], CP_SET_SECURE_MODE, 1); + OUT_RING(gpu->rb[0], 0x00000000); + + a6xx_flush(gpu, gpu->rb[0]); + if (!a8xx_idle(gpu, gpu->rb[0])) + return -EINVAL; + } else if (ret == -ENODEV) { + /* + * This device does not use zap shader (but print a warning + * just in case someone got their dt wrong.. hopefully they + * have a debug UART to realize the error of their ways... + * if you mess this up you are about to crash horribly) + */ + dev_warn_once(gpu->dev->dev, + "Zap shader not enabled - using SECVID_TRUST_CNTL instead\n"); + gpu_write(gpu, REG_A6XX_RBBM_SECVID_TRUST_CNTL, 0x0); + ret = 0; + } else { + return ret; + } + + /* + * GMEM_PROTECT register should be programmed after GPU is transitioned to + * non-secure mode + */ + a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_RB_GC_GMEM_PROTECT, gmem_protect); + WARN_ON(!gmem_protect); + a8xx_aperture_clear(gpu); + + /* Enable hardware clockgating */ + a8xx_set_hwcg(gpu, true); +out: + /* + * Tell the GMU that we are done touching the GPU and it can start power + * management + */ + a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); + + return ret; +} + +int a8xx_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); + int ret; + + mutex_lock(&a6xx_gpu->gmu.lock); + ret = hw_init(gpu); + mutex_unlock(&a6xx_gpu->gmu.lock); + + return ret; +} + +static void a8xx_dump(struct msm_gpu *gpu) +{ + DRM_DEV_INFO(&gpu->pdev->dev, "status: %08x\n", gpu_read(gpu, REG_A8XX_RBBM_STATUS)); + adreno_dump(gpu); +} + +void a8xx_recover(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; + int active_submits; + + adreno_dump_info(gpu); + + if (hang_debug) + a8xx_dump(gpu); + + /* + * To handle recovery specific sequences during the rpm suspend we are + * about to trigger + */ + a6xx_gpu->hung = true; + + /* Halt SQE first */ + gpu_write(gpu, REG_A8XX_CP_SQE_CNTL, 3); + + pm_runtime_dont_use_autosuspend(&gpu->pdev->dev); + + /* active_submit won't change until we make a submission */ + mutex_lock(&gpu->active_lock); + active_submits = gpu->active_submits; + + /* + * Temporarily clear active_submits count to silence a WARN() in the + * runtime suspend cb + */ + gpu->active_submits = 0; + + reinit_completion(&gmu->pd_gate); + dev_pm_genpd_add_notifier(gmu->cxpd, &gmu->pd_nb); + dev_pm_genpd_synced_poweroff(gmu->cxpd); + + /* Drop the rpm refcount from active submits */ + if (active_submits) + pm_runtime_put(&gpu->pdev->dev); + + /* And the final one from recover worker */ + pm_runtime_put_sync(&gpu->pdev->dev); + + if (!wait_for_completion_timeout(&gmu->pd_gate, msecs_to_jiffies(1000))) + DRM_DEV_ERROR(&gpu->pdev->dev, "cx gdsc didn't collapse\n"); + + dev_pm_genpd_remove_notifier(gmu->cxpd); + + pm_runtime_use_autosuspend(&gpu->pdev->dev); + + if (active_submits) + pm_runtime_get(&gpu->pdev->dev); + + pm_runtime_get_sync(&gpu->pdev->dev); + + gpu->active_submits = active_submits; + mutex_unlock(&gpu->active_lock); + + msm_gpu_hw_init(gpu); + a6xx_gpu->hung = false; +} + +static const char *a8xx_uche_fault_block(struct msm_gpu *gpu, u32 mid) +{ + static const char * const uche_clients[] = { + "BR_VFD", "BR_SP", "BR_VSC", "BR_VPC", "BR_HLSQ", "BR_PC", "BR_LRZ", "BR_TP", + "BV_VFD", "BV_SP", "BV_VSC", "BV_VPC", "BV_HLSQ", "BV_PC", "BV_LRZ", "BV_TP", + "STCHE", + }; + static const char * const uche_clients_lpac[] = { + "-", "SP_LPAC", "-", "-", "HLSQ_LPAC", "-", "-", "TP_LPAC", + }; + u32 val; + + /* + * The source of the data depends on the mid ID read from FSYNR1. + * and the client ID read from the UCHE block + */ + val = gpu_read(gpu, REG_A8XX_UCHE_CLIENT_PF); + + val &= GENMASK(6, 0); + + /* mid=3 refers to BR or BV */ + if (mid == 3) { + if (val < ARRAY_SIZE(uche_clients)) + return uche_clients[val]; + else + return "UCHE"; + } + + /* mid=8 refers to LPAC */ + if (mid == 8) { + if (val < ARRAY_SIZE(uche_clients_lpac)) + return uche_clients_lpac[val]; + else + return "UCHE_LPAC"; + } + + return "Unknown"; +} + +static const char *a8xx_fault_block(struct msm_gpu *gpu, u32 id) +{ + switch (id) { + case 0x0: + return "CP"; + case 0x1: + return "UCHE: Unknown"; + case 0x2: + return "UCHE_LPAC: Unknown"; + case 0x3: + case 0x8: + return a8xx_uche_fault_block(gpu, id); + case 0x4: + return "CCU"; + case 0x5: + return "Flag cache"; + case 0x6: + return "PREFETCH"; + case 0x7: + return "GMU"; + case 0x9: + return "UCHE_HPAC"; + } + + return "Unknown"; +} + +int a8xx_fault_handler(void *arg, unsigned long iova, int flags, void *data) +{ + struct msm_gpu *gpu = arg; + struct adreno_smmu_fault_info *info = data; + const char *block = "unknown"; + + u32 scratch[] = { + gpu_read(gpu, REG_A8XX_CP_SCRATCH_GLOBAL(0)), + gpu_read(gpu, REG_A8XX_CP_SCRATCH_GLOBAL(1)), + gpu_read(gpu, REG_A8XX_CP_SCRATCH_GLOBAL(2)), + gpu_read(gpu, REG_A8XX_CP_SCRATCH_GLOBAL(3)), + }; + + if (info) + block = a8xx_fault_block(gpu, info->fsynr1 & 0xff); + + return adreno_fault_handler(gpu, iova, flags, info, block, scratch); +} + +static void a8xx_cp_hw_err_irq(struct msm_gpu *gpu) +{ + u32 status = gpu_read(gpu, REG_A8XX_CP_INTERRUPT_STATUS_GLOBAL); + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + u32 slice = a8xx_get_first_slice(a6xx_gpu); + u32 hw_fault_mask = GENMASK(6, 0); + u32 sw_fault_mask = GENMASK(22, 16); + u32 pipe = 0; + + dev_err_ratelimited(&gpu->pdev->dev, "CP Fault Global INT status: 0x%x\n", status); + + if (status & (A8XX_CP_GLOBAL_INT_MASK_HWFAULTBR | + A8XX_CP_GLOBAL_INT_MASK_SWFAULTBR)) + pipe |= BIT(PIPE_BR); + + if (status & (A8XX_CP_GLOBAL_INT_MASK_HWFAULTBV | + A8XX_CP_GLOBAL_INT_MASK_SWFAULTBV)) + pipe |= BIT(PIPE_BV); + + if (!pipe) { + dev_err_ratelimited(&gpu->pdev->dev, "CP Fault Unknown pipe\n"); + goto out; + } + + for (unsigned int pipe_id = PIPE_NONE; pipe_id <= PIPE_DDE_BV; pipe_id++) { + if (!(BIT(pipe_id) & pipe)) + continue; + + if (hw_fault_mask & status) { + status = a8xx_read_pipe_slice(gpu, pipe_id, slice, + REG_A8XX_CP_HW_FAULT_STATUS_PIPE); + dev_err_ratelimited(&gpu->pdev->dev, + "CP HW FAULT pipe: %u status: 0x%x\n", pipe_id, status); + } + + if (sw_fault_mask & status) { + status = a8xx_read_pipe_slice(gpu, pipe_id, slice, + REG_A8XX_CP_INTERRUPT_STATUS_PIPE); + dev_err_ratelimited(&gpu->pdev->dev, + "CP SW FAULT pipe: %u status: 0x%x\n", pipe_id, status); + + if (status & BIT(8)) { + a8xx_write_pipe(gpu, pipe_id, REG_A8XX_CP_SQE_STAT_ADDR_PIPE, 1); + status = a8xx_read_pipe_slice(gpu, pipe_id, slice, + REG_A8XX_CP_SQE_STAT_DATA_PIPE); + dev_err_ratelimited(&gpu->pdev->dev, + "CP Opcode error, opcode=0x%x\n", status); + } + + if (status & BIT(10)) { + status = a8xx_read_pipe_slice(gpu, pipe_id, slice, + REG_A8XX_CP_PROTECT_STATUS_PIPE); + dev_err_ratelimited(&gpu->pdev->dev, + "CP REG PROTECT error, status=0x%x\n", status); + } + } + } + +out: + /* Turn off interrupts to avoid triggering recovery again */ + a8xx_aperture_clear(gpu); + gpu_write(gpu, REG_A8XX_CP_INTERRUPT_STATUS_MASK_GLOBAL, 0); + gpu_write(gpu, REG_A8XX_RBBM_INT_0_MASK, 0); + + kthread_queue_work(gpu->worker, &gpu->recover_work); +} + +static u32 gpu_periph_read(struct msm_gpu *gpu, u32 dbg_offset) +{ + gpu_write(gpu, REG_A8XX_CP_SQE_UCODE_DBG_ADDR_PIPE, dbg_offset); + + return gpu_read(gpu, REG_A8XX_CP_SQE_UCODE_DBG_DATA_PIPE); +} + +static u64 gpu_periph_read64(struct msm_gpu *gpu, u32 dbg_offset) +{ + u64 lo, hi; + + lo = gpu_periph_read(gpu, dbg_offset); + hi = gpu_periph_read(gpu, dbg_offset + 1); + + return (hi << 32) | lo; +} + +#define CP_PERIPH_IB1_BASE_LO 0x7005 +#define CP_PERIPH_IB1_BASE_HI 0x7006 +#define CP_PERIPH_IB1_SIZE 0x7007 +#define CP_PERIPH_IB1_OFFSET 0x7008 +#define CP_PERIPH_IB2_BASE_LO 0x7009 +#define CP_PERIPH_IB2_BASE_HI 0x700a +#define CP_PERIPH_IB2_SIZE 0x700b +#define CP_PERIPH_IB2_OFFSET 0x700c +#define CP_PERIPH_IB3_BASE_LO 0x700d +#define CP_PERIPH_IB3_BASE_HI 0x700e +#define CP_PERIPH_IB3_SIZE 0x700f +#define CP_PERIPH_IB3_OFFSET 0x7010 + +static void a8xx_fault_detect_irq(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu); + unsigned long flags; + + /* + * If stalled on SMMU fault, we could trip the GPU's hang detection, + * but the fault handler will trigger the devcore dump, and we want + * to otherwise resume normally rather than killing the submit, so + * just bail. + */ + if (gpu_read(gpu, REG_A8XX_RBBM_MISC_STATUS) & A8XX_RBBM_MISC_STATUS_SMMU_STALLED_ON_FAULT) + return; + + /* + * Force the GPU to stay on until after we finish + * collecting information + */ + if (!adreno_has_gmu_wrapper(adreno_gpu)) + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 1); + + DRM_DEV_ERROR(&gpu->pdev->dev, + "gpu fault ring %d fence %x status %8.8X gfx_status %8.8X\n", + ring ? ring->id : -1, ring ? ring->fctx->last_fence : 0, + gpu_read(gpu, REG_A8XX_RBBM_STATUS), gpu_read(gpu, REG_A8XX_RBBM_GFX_STATUS)); + + a8xx_aperture_acquire(gpu, PIPE_BR, &flags); + + DRM_DEV_ERROR(&gpu->pdev->dev, + "BR: status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x ib3 %16.16llX/%4.4x\n", + gpu_read(gpu, REG_A8XX_RBBM_GFX_BR_STATUS), + gpu_read(gpu, REG_A6XX_CP_RB_RPTR), + gpu_read(gpu, REG_A6XX_CP_RB_WPTR), + gpu_periph_read64(gpu, CP_PERIPH_IB1_BASE_LO), + gpu_periph_read(gpu, CP_PERIPH_IB1_OFFSET), + gpu_periph_read64(gpu, CP_PERIPH_IB2_BASE_LO), + gpu_periph_read(gpu, CP_PERIPH_IB2_OFFSET), + gpu_periph_read64(gpu, CP_PERIPH_IB3_BASE_LO), + gpu_periph_read(gpu, CP_PERIPH_IB3_OFFSET)); + + a8xx_aperture_release(gpu, flags); + a8xx_aperture_acquire(gpu, PIPE_BV, &flags); + + DRM_DEV_ERROR(&gpu->pdev->dev, + "BV: status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x ib3 %16.16llX/%4.4x\n", + gpu_read(gpu, REG_A8XX_RBBM_GFX_BV_STATUS), + gpu_read(gpu, REG_A8XX_CP_RB_RPTR_BV), + gpu_read(gpu, REG_A6XX_CP_RB_WPTR), + gpu_periph_read64(gpu, CP_PERIPH_IB1_BASE_LO), + gpu_periph_read(gpu, CP_PERIPH_IB1_OFFSET), + gpu_periph_read64(gpu, CP_PERIPH_IB2_BASE_LO), + gpu_periph_read(gpu, CP_PERIPH_IB2_OFFSET), + gpu_periph_read64(gpu, CP_PERIPH_IB3_BASE_LO), + gpu_periph_read(gpu, CP_PERIPH_IB3_OFFSET)); + + a8xx_aperture_release(gpu, flags); + a8xx_aperture_clear(gpu); + + /* Turn off the hangcheck timer to keep it from bothering us */ + timer_delete(&gpu->hangcheck_timer); + + kthread_queue_work(gpu->worker, &gpu->recover_work); +} + +static void a8xx_sw_fuse_violation_irq(struct msm_gpu *gpu) +{ + u32 status; + + status = gpu_read(gpu, REG_A8XX_RBBM_SW_FUSE_INT_STATUS); + gpu_write(gpu, REG_A8XX_RBBM_SW_FUSE_INT_MASK, 0); + + dev_err_ratelimited(&gpu->pdev->dev, "SW fuse violation status=%8.8x\n", status); + + /* + * Ignore FASTBLEND violations, because the HW will silently fall back + * to legacy blending. + */ + if (status & (A7XX_CX_MISC_SW_FUSE_VALUE_RAYTRACING | + A7XX_CX_MISC_SW_FUSE_VALUE_LPAC)) { + timer_delete(&gpu->hangcheck_timer); + + kthread_queue_work(gpu->worker, &gpu->recover_work); + } +} + +irqreturn_t a8xx_irq(struct msm_gpu *gpu) +{ + struct msm_drm_private *priv = gpu->dev->dev_private; + u32 status = gpu_read(gpu, REG_A8XX_RBBM_INT_0_STATUS); + + gpu_write(gpu, REG_A8XX_RBBM_INT_CLEAR_CMD, status); + + if (priv->disable_err_irq) + status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS; + + if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) + a8xx_fault_detect_irq(gpu); + + if (status & A6XX_RBBM_INT_0_MASK_CP_AHB_ERROR) { + u32 rl0, rl1; + + rl0 = gpu_read(gpu, REG_A8XX_CP_RL_ERROR_DETAILS_0); + rl1 = gpu_read(gpu, REG_A8XX_CP_RL_ERROR_DETAILS_1); + dev_err_ratelimited(&gpu->pdev->dev, + "CP | AHB bus error RL_ERROR_0: %x, RL_ERROR_1: %x\n", rl0, rl1); + } + + if (status & A6XX_RBBM_INT_0_MASK_CP_HW_ERROR) + a8xx_cp_hw_err_irq(gpu); + + if (status & A6XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNCFIFO_OVERFLOW) + dev_err_ratelimited(&gpu->pdev->dev, "RBBM | ATB ASYNC overflow\n"); + + if (status & A6XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW) + dev_err_ratelimited(&gpu->pdev->dev, "RBBM | ATB bus overflow\n"); + + if (status & A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS) + dev_err_ratelimited(&gpu->pdev->dev, "UCHE | Out of bounds access\n"); + + if (status & A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR) + dev_err_ratelimited(&gpu->pdev->dev, "UCHE | Trap interrupt\n"); + + if (status & A6XX_RBBM_INT_0_MASK_SWFUSEVIOLATION) + a8xx_sw_fuse_violation_irq(gpu); + + if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS) { + msm_gpu_retire(gpu); + a6xx_preempt_trigger(gpu); + } + + if (status & A6XX_RBBM_INT_0_MASK_CP_SW) + a6xx_preempt_irq(gpu); + + return IRQ_HANDLED; +} + +void a8xx_llc_activate(struct a6xx_gpu *a6xx_gpu) +{ + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + struct msm_gpu *gpu = &adreno_gpu->base; + + if (!llcc_slice_activate(a6xx_gpu->llc_slice)) { + u32 gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice); + + gpu_scid &= GENMASK(5, 0); + + gpu_write(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, + FIELD_PREP(GENMASK(29, 24), gpu_scid) | + FIELD_PREP(GENMASK(23, 18), gpu_scid) | + FIELD_PREP(GENMASK(17, 12), gpu_scid) | + FIELD_PREP(GENMASK(11, 6), gpu_scid) | + FIELD_PREP(GENMASK(5, 0), gpu_scid)); + + gpu_write(gpu, REG_A6XX_GBIF_SCACHE_CNTL0, + FIELD_PREP(GENMASK(27, 22), gpu_scid) | + FIELD_PREP(GENMASK(21, 16), gpu_scid) | + FIELD_PREP(GENMASK(15, 10), gpu_scid) | + BIT(8)); + } + + llcc_slice_activate(a6xx_gpu->htw_llc_slice); +} + +#define GBIF_CLIENT_HALT_MASK BIT(0) +#define GBIF_ARB_HALT_MASK BIT(1) +#define VBIF_XIN_HALT_CTRL0_MASK GENMASK(3, 0) +#define VBIF_RESET_ACK_MASK 0xF0 +#define GPR0_GBIF_HALT_REQUEST 0x1E0 + +void a8xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off) +{ + struct msm_gpu *gpu = &adreno_gpu->base; + + if (gx_off) { + /* Halt the gx side of GBIF */ + gpu_write(gpu, REG_A8XX_RBBM_GBIF_HALT, 1); + spin_until(gpu_read(gpu, REG_A8XX_RBBM_GBIF_HALT_ACK) & 1); + } + + /* Halt new client requests on GBIF */ + gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK); + spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) & + (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK); + + /* Halt all AXI requests on GBIF */ + gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK); + spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) & + (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK); + + /* The GBIF halt needs to be explicitly cleared */ + gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0); +} + +int a8xx_gmu_get_timestamp(struct msm_gpu *gpu, uint64_t *value) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + + mutex_lock(&a6xx_gpu->gmu.lock); + + /* Force the GPU power on so we can read this register */ + a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); + + *value = gpu_read64(gpu, REG_A8XX_CP_ALWAYS_ON_COUNTER); + + a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); + + mutex_unlock(&a6xx_gpu->gmu.lock); + + return 0; +} + +u64 a8xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + u64 busy_cycles; + + /* 19.2MHz */ + *out_sample_rate = 19200000; + + busy_cycles = gmu_read64(&a6xx_gpu->gmu, + REG_A8XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L, + REG_A8XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H); + + return busy_cycles; +} + +bool a8xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +{ + return true; +} diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 9ffe91920fbf..554d746f115b 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -16,20 +16,25 @@ bool snapshot_debugbus = false; MODULE_PARM_DESC(snapshot_debugbus, "Include debugbus sections in GPU devcoredump (if not fused off)"); module_param_named(snapshot_debugbus, snapshot_debugbus, bool, 0600); -bool allow_vram_carveout = false; -MODULE_PARM_DESC(allow_vram_carveout, "Allow using VRAM Carveout, in place of IOMMU"); -module_param_named(allow_vram_carveout, allow_vram_carveout, bool, 0600); - int enable_preemption = -1; MODULE_PARM_DESC(enable_preemption, "Enable preemption (A7xx only) (1=on , 0=disable, -1=auto (default))"); module_param(enable_preemption, int, 0600); +bool disable_acd; +MODULE_PARM_DESC(disable_acd, "Forcefully disable GPU ACD"); +module_param_unsafe(disable_acd, bool, 0400); + +static bool skip_gpu; +MODULE_PARM_DESC(no_gpu, "Disable GPU driver register (0=enable GPU driver register (default), 1=skip GPU driver register"); +module_param(skip_gpu, bool, 0400); + extern const struct adreno_gpulist a2xx_gpulist; extern const struct adreno_gpulist a3xx_gpulist; extern const struct adreno_gpulist a4xx_gpulist; extern const struct adreno_gpulist a5xx_gpulist; extern const struct adreno_gpulist a6xx_gpulist; extern const struct adreno_gpulist a7xx_gpulist; +extern const struct adreno_gpulist a8xx_gpulist; static const struct adreno_gpulist *gpulists[] = { &a2xx_gpulist, @@ -38,6 +43,7 @@ static const struct adreno_gpulist *gpulists[] = { &a5xx_gpulist, &a6xx_gpulist, &a7xx_gpulist, + &a8xx_gpulist, }; static const struct adreno_info *adreno_info(uint32_t chip_id) @@ -133,9 +139,8 @@ err_disable_rpm: return NULL; } -static int find_chipid(struct device *dev, uint32_t *chipid) +static int find_chipid(struct device_node *node, uint32_t *chipid) { - struct device_node *node = dev->of_node; const char *compat; int ret; @@ -169,15 +174,39 @@ static int find_chipid(struct device *dev, uint32_t *chipid) /* and if that fails, fall back to legacy "qcom,chipid" property: */ ret = of_property_read_u32(node, "qcom,chipid", chipid); if (ret) { - DRM_DEV_ERROR(dev, "could not parse qcom,chipid: %d\n", ret); + DRM_ERROR("%pOF: could not parse qcom,chipid: %d\n", + node, ret); return ret; } - dev_warn(dev, "Using legacy qcom,chipid binding!\n"); + pr_warn("%pOF: Using legacy qcom,chipid binding!\n", node); return 0; } +bool adreno_has_gpu(struct device_node *node) +{ + const struct adreno_info *info; + uint32_t chip_id; + int ret; + + if (skip_gpu) + return false; + + ret = find_chipid(node, &chip_id); + if (ret) + return false; + + info = adreno_info(chip_id); + if (!info) { + pr_warn("%pOF: Unknown GPU revision: %"ADRENO_CHIPID_FMT"\n", + node, ADRENO_CHIPID_ARGS(chip_id)); + return false; + } + + return true; +} + static int adreno_bind(struct device *dev, struct device *master, void *data) { static struct adreno_platform_config config = {}; @@ -187,19 +216,18 @@ static int adreno_bind(struct device *dev, struct device *master, void *data) struct msm_gpu *gpu; int ret; - ret = find_chipid(dev, &config.chip_id); - if (ret) + ret = find_chipid(dev->of_node, &config.chip_id); + /* We shouldn't have gotten this far if we can't parse the chip_id */ + if (WARN_ON(ret)) return ret; dev->platform_data = &config; priv->gpu_pdev = to_platform_device(dev); info = adreno_info(config.chip_id); - if (!info) { - dev_warn(drm->dev, "Unknown GPU revision: %"ADRENO_CHIPID_FMT"\n", - ADRENO_CHIPID_ARGS(config.chip_id)); + /* We shouldn't have gotten this far if we don't recognize the GPU: */ + if (WARN_ON(!info)) return -ENXIO; - } config.info = info; @@ -209,7 +237,7 @@ static int adreno_bind(struct device *dev, struct device *master, void *data) priv->has_cached_coherent = !!(info->quirks & ADRENO_QUIRK_HAS_CACHED_COHERENT); - gpu = info->init(drm); + gpu = info->funcs->init(drm); if (IS_ERR(gpu)) { dev_warn(drm->dev, "failed to load adreno gpu\n"); return PTR_ERR(gpu); @@ -241,42 +269,23 @@ static const struct component_ops a3xx_ops = { .unbind = adreno_unbind, }; -static void adreno_device_register_headless(void) -{ - /* on imx5, we don't have a top-level mdp/dpu node - * this creates a dummy node for the driver for that case - */ - struct platform_device_info dummy_info = { - .parent = NULL, - .name = "msm", - .id = -1, - .res = NULL, - .num_res = 0, - .data = NULL, - .size_data = 0, - .dma_mask = ~0, - }; - platform_device_register_full(&dummy_info); -} - static int adreno_probe(struct platform_device *pdev) { + if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon") || + msm_gpu_no_components()) + return msm_gpu_probe(pdev, &a3xx_ops); - int ret; - - ret = component_add(&pdev->dev, &a3xx_ops); - if (ret) - return ret; - - if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon")) - adreno_device_register_headless(); - - return 0; + return component_add(&pdev->dev, &a3xx_ops); } static void adreno_remove(struct platform_device *pdev) { - component_del(&pdev->dev, &a3xx_ops); + struct msm_drm_private *priv = platform_get_drvdata(pdev); + + if (priv->kms_init) + component_del(&pdev->dev, &a3xx_ops); + else + msm_gpu_remove(pdev, &a3xx_ops); } static void adreno_shutdown(struct platform_device *pdev) @@ -393,7 +402,7 @@ static const struct dev_pm_ops adreno_pm_ops = { static struct platform_driver adreno_driver = { .probe = adreno_probe, - .remove_new = adreno_remove, + .remove = adreno_remove, .shutdown = adreno_shutdown, .driver = { .name = "adreno", @@ -404,10 +413,16 @@ static struct platform_driver adreno_driver = { void __init adreno_register(void) { + if (skip_gpu) + return; + platform_driver_register(&adreno_driver); } void __exit adreno_unregister(void) { + if (skip_gpu) + return; + platform_driver_unregister(&adreno_driver); } diff --git a/drivers/gpu/drm/msm/adreno/adreno_gen7_0_0_snapshot.h b/drivers/gpu/drm/msm/adreno/adreno_gen7_0_0_snapshot.h index cb66ece6606b..d513e03fef08 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gen7_0_0_snapshot.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gen7_0_0_snapshot.h @@ -81,86 +81,86 @@ static const u32 gen7_0_0_debugbus_blocks[] = { A7XX_DBGBUS_USPTP_7, }; -static struct gen7_shader_block gen7_0_0_shader_blocks[] = { - {A7XX_TP0_TMO_DATA, 0x200, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_TP0_SMO_DATA, 0x80, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_TP0_MIPMAP_BASE_DATA, 0x3c0, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_INST_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_INST_DATA_1, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_0_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_1_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_2_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_3_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_4_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_5_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_6_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_7_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_CB_RAM, 0x390, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_INST_TAG, 0x90, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_INST_DATA_2, 0x200, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_TMO_TAG, 0x80, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_SMO_TAG, 0x80, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_STATE_DATA, 0x40, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_HWAVE_RAM, 0x100, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_L0_INST_BUF, 0x50, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_8_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_9_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_10_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_11_DATA, 0x800, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_12_DATA, 0x200, 4, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x300, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x300, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CPS_BE_CTXT_BUF_RAM, 0x300, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CVS_RAM, 0x1c0, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CVS_RAM, 0x1c0, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CPS_RAM, 0x300, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CPS_RAM, 0x300, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x40, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x40, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x40, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x40, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x10, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x10, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CVS_MISC_RAM, 0x280, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CVS_MISC_RAM, 0x280, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_MISC_RAM, 0x800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_MISC_RAM, 0x800, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_MISC_RAM_1, 0x200, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM, 0x800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM, 0x800, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM, 0x800, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x800, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x800, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x64, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x64, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x64, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x64, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM_1, 0x800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_STPROC_META, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_BV_BE_META, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_BV_BE_META, 0x10, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_DATAPATH_META, 0x20, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_FRONTEND_META, 0x40, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_FRONTEND_META, 0x40, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_FRONTEND_META, 0x40, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INDIRECT_META, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, +static const struct gen7_shader_block gen7_0_0_shader_blocks[] = { + {A7XX_TP0_TMO_DATA, 0x200, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_TP0_SMO_DATA, 0x80, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_TP0_MIPMAP_BASE_DATA, 0x3c0, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_INST_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_INST_DATA_1, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_0_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_1_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_2_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_3_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_4_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_5_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_6_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_7_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_CB_RAM, 0x390, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_INST_TAG, 0x90, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_INST_DATA_2, 0x200, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_TMO_TAG, 0x80, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_SMO_TAG, 0x80, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_STATE_DATA, 0x40, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_HWAVE_RAM, 0x100, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_L0_INST_BUF, 0x50, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_8_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_9_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_10_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_11_DATA, 0x800, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_12_DATA, 0x200, 4, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x300, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x300, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CPS_BE_CTXT_BUF_RAM, 0x300, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CVS_RAM, 0x1c0, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CVS_RAM, 0x1c0, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CPS_RAM, 0x300, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CPS_RAM, 0x300, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x40, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x40, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x40, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x40, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x10, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x10, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CVS_MISC_RAM, 0x280, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CVS_MISC_RAM, 0x280, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_MISC_RAM, 0x800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_MISC_RAM, 0x800, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_MISC_RAM_1, 0x200, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM, 0x800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM, 0x800, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM, 0x800, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x800, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x800, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x10, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x10, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x64, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x64, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x64, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x64, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM_1, 0x800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_STPROC_META, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_BV_BE_META, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_BV_BE_META, 0x10, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_DATAPATH_META, 0x20, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_FRONTEND_META, 0x40, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_FRONTEND_META, 0x40, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_FRONTEND_META, 0x40, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INDIRECT_META, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, }; static const u32 gen7_0_0_pre_crashdumper_gpu_registers[] = { @@ -303,7 +303,7 @@ static const u32 gen7_0_0_noncontext_rb_rbp_pipe_br_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_noncontext_rb_rbp_pipe_br_registers), 8)); -/* Block: GRAS Cluster: A7XX_CLUSTER_GRAS Pipeline: A7XX_PIPE_BR */ +/* Block: GRAS Cluster: A7XX_CLUSTER_GRAS Pipeline: PIPE_BR */ static const u32 gen7_0_0_gras_cluster_gras_pipe_br_registers[] = { 0x08000, 0x08008, 0x08010, 0x08092, 0x08094, 0x08099, 0x0809b, 0x0809d, 0x080a0, 0x080a7, 0x080af, 0x080f1, 0x080f4, 0x080f6, 0x080f8, 0x080fa, @@ -313,7 +313,7 @@ static const u32 gen7_0_0_gras_cluster_gras_pipe_br_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_gras_cluster_gras_pipe_br_registers), 8)); -/* Block: GRAS Cluster: A7XX_CLUSTER_GRAS Pipeline: A7XX_PIPE_BV */ +/* Block: GRAS Cluster: A7XX_CLUSTER_GRAS Pipeline: PIPE_BV */ static const u32 gen7_0_0_gras_cluster_gras_pipe_bv_registers[] = { 0x08000, 0x08008, 0x08010, 0x08092, 0x08094, 0x08099, 0x0809b, 0x0809d, 0x080a0, 0x080a7, 0x080af, 0x080f1, 0x080f4, 0x080f6, 0x080f8, 0x080fa, @@ -323,7 +323,7 @@ static const u32 gen7_0_0_gras_cluster_gras_pipe_bv_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_gras_cluster_gras_pipe_bv_registers), 8)); -/* Block: PC Cluster: A7XX_CLUSTER_FE Pipeline: A7XX_PIPE_BR */ +/* Block: PC Cluster: A7XX_CLUSTER_FE Pipeline: PIPE_BR */ static const u32 gen7_0_0_pc_cluster_fe_pipe_br_registers[] = { 0x09800, 0x09804, 0x09806, 0x0980a, 0x09810, 0x09811, 0x09884, 0x09886, 0x09b00, 0x09b08, @@ -331,7 +331,7 @@ static const u32 gen7_0_0_pc_cluster_fe_pipe_br_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_pc_cluster_fe_pipe_br_registers), 8)); -/* Block: PC Cluster: A7XX_CLUSTER_FE Pipeline: A7XX_PIPE_BV */ +/* Block: PC Cluster: A7XX_CLUSTER_FE Pipeline: PIPE_BV */ static const u32 gen7_0_0_pc_cluster_fe_pipe_bv_registers[] = { 0x09800, 0x09804, 0x09806, 0x0980a, 0x09810, 0x09811, 0x09884, 0x09886, 0x09b00, 0x09b08, @@ -339,7 +339,7 @@ static const u32 gen7_0_0_pc_cluster_fe_pipe_bv_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_pc_cluster_fe_pipe_bv_registers), 8)); -/* Block: RB_RAC Cluster: A7XX_CLUSTER_PS Pipeline: A7XX_PIPE_BR */ +/* Block: RB_RAC Cluster: A7XX_CLUSTER_PS Pipeline: PIPE_BR */ static const u32 gen7_0_0_rb_rac_cluster_ps_pipe_br_registers[] = { 0x08802, 0x08802, 0x08804, 0x08806, 0x08809, 0x0880a, 0x0880e, 0x08811, 0x08818, 0x0881e, 0x08821, 0x08821, 0x08823, 0x08826, 0x08829, 0x08829, @@ -355,7 +355,7 @@ static const u32 gen7_0_0_rb_rac_cluster_ps_pipe_br_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_rb_rac_cluster_ps_pipe_br_registers), 8)); -/* Block: RB_RBP Cluster: A7XX_CLUSTER_PS Pipeline: A7XX_PIPE_BR */ +/* Block: RB_RBP Cluster: A7XX_CLUSTER_PS Pipeline: PIPE_BR */ static const u32 gen7_0_0_rb_rbp_cluster_ps_pipe_br_registers[] = { 0x08800, 0x08801, 0x08803, 0x08803, 0x0880b, 0x0880d, 0x08812, 0x08812, 0x08820, 0x08820, 0x08822, 0x08822, 0x08827, 0x08828, 0x0882a, 0x0882a, @@ -370,7 +370,7 @@ static const u32 gen7_0_0_rb_rbp_cluster_ps_pipe_br_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_rb_rbp_cluster_ps_pipe_br_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_BR Location: HLSQ_STATE */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_BR Location: HLSQ_STATE */ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_state_registers[] = { 0x0a980, 0x0a980, 0x0a982, 0x0a984, 0x0a99e, 0x0a99e, 0x0a9a7, 0x0a9a7, 0x0a9aa, 0x0a9aa, 0x0a9ae, 0x0a9b0, 0x0a9b3, 0x0a9b5, 0x0a9ba, 0x0a9ba, @@ -381,7 +381,7 @@ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_state_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_state_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_LPAC Location: HLSQ_STATE */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_LPAC Location: HLSQ_STATE */ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_lpac_hlsq_state_registers[] = { 0x0a9b0, 0x0a9b0, 0x0a9b3, 0x0a9b5, 0x0a9ba, 0x0a9ba, 0x0a9bc, 0x0a9bc, 0x0a9c4, 0x0a9c4, 0x0a9cd, 0x0a9cd, 0x0a9e2, 0x0a9e3, 0x0a9e6, 0x0a9fc, @@ -390,21 +390,21 @@ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_lpac_hlsq_state_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_ps_pipe_lpac_hlsq_state_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_BR Location: HLSQ_DP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_BR Location: HLSQ_DP */ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers[] = { 0x0a9b1, 0x0a9b1, 0x0a9c6, 0x0a9cb, 0x0a9d4, 0x0a9df, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_LPAC Location: HLSQ_DP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_LPAC Location: HLSQ_DP */ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_lpac_hlsq_dp_registers[] = { 0x0a9b1, 0x0a9b1, 0x0a9d4, 0x0a9df, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_ps_pipe_lpac_hlsq_dp_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_BR Location: SP_TOP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_BR Location: SP_TOP */ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_br_sp_top_registers[] = { 0x0a980, 0x0a980, 0x0a982, 0x0a984, 0x0a99e, 0x0a9a2, 0x0a9a7, 0x0a9a8, 0x0a9aa, 0x0a9aa, 0x0a9ae, 0x0a9ae, 0x0a9b0, 0x0a9b1, 0x0a9b3, 0x0a9b5, @@ -414,7 +414,7 @@ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_br_sp_top_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_ps_pipe_br_sp_top_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_LPAC Location: SP_TOP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_LPAC Location: SP_TOP */ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_lpac_sp_top_registers[] = { 0x0a9b0, 0x0a9b1, 0x0a9b3, 0x0a9b5, 0x0a9ba, 0x0a9bc, 0x0a9e2, 0x0a9e3, 0x0a9e6, 0x0a9f9, 0x0aa00, 0x0aa00, 0x0ab00, 0x0ab00, @@ -422,7 +422,7 @@ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_lpac_sp_top_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_ps_pipe_lpac_sp_top_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_BR Location: uSPTP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_BR Location: uSPTP */ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_br_usptp_registers[] = { 0x0a980, 0x0a982, 0x0a985, 0x0a9a6, 0x0a9a8, 0x0a9a9, 0x0a9ab, 0x0a9ae, 0x0a9b0, 0x0a9b3, 0x0a9b6, 0x0a9b9, 0x0a9bb, 0x0a9bf, 0x0a9c2, 0x0a9c3, @@ -432,7 +432,7 @@ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_br_usptp_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_ps_pipe_br_usptp_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_LPAC Location: uSPTP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_LPAC Location: uSPTP */ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_lpac_usptp_registers[] = { 0x0a9b0, 0x0a9b3, 0x0a9b6, 0x0a9b9, 0x0a9bb, 0x0a9be, 0x0a9c2, 0x0a9c3, 0x0a9cd, 0x0a9cd, 0x0a9d0, 0x0a9d3, 0x0aa31, 0x0aa31, 0x0ab00, 0x0ab01, @@ -440,7 +440,7 @@ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_lpac_usptp_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_ps_pipe_lpac_usptp_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: A7XX_PIPE_BR Location: HLSQ_STATE */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: PIPE_BR Location: HLSQ_STATE */ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_br_hlsq_state_registers[] = { 0x0a800, 0x0a800, 0x0a81b, 0x0a81d, 0x0a822, 0x0a822, 0x0a824, 0x0a824, 0x0a827, 0x0a82a, 0x0a830, 0x0a830, 0x0a833, 0x0a835, 0x0a83a, 0x0a83a, @@ -453,7 +453,7 @@ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_br_hlsq_state_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_vs_pipe_br_hlsq_state_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: A7XX_PIPE_BV Location: HLSQ_STATE */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: PIPE_BV Location: HLSQ_STATE */ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_bv_hlsq_state_registers[] = { 0x0a800, 0x0a800, 0x0a81b, 0x0a81d, 0x0a822, 0x0a822, 0x0a824, 0x0a824, 0x0a827, 0x0a82a, 0x0a830, 0x0a830, 0x0a833, 0x0a835, 0x0a83a, 0x0a83a, @@ -466,7 +466,7 @@ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_bv_hlsq_state_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_vs_pipe_bv_hlsq_state_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: A7XX_PIPE_BR Location: SP_TOP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: PIPE_BR Location: SP_TOP */ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_br_sp_top_registers[] = { 0x0a800, 0x0a800, 0x0a81c, 0x0a81d, 0x0a822, 0x0a824, 0x0a830, 0x0a831, 0x0a834, 0x0a835, 0x0a83a, 0x0a83c, 0x0a840, 0x0a840, 0x0a85c, 0x0a85d, @@ -477,7 +477,7 @@ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_br_sp_top_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_vs_pipe_br_sp_top_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: A7XX_PIPE_BV Location: SP_TOP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: PIPE_BV Location: SP_TOP */ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_bv_sp_top_registers[] = { 0x0a800, 0x0a800, 0x0a81c, 0x0a81d, 0x0a822, 0x0a824, 0x0a830, 0x0a831, 0x0a834, 0x0a835, 0x0a83a, 0x0a83c, 0x0a840, 0x0a840, 0x0a85c, 0x0a85d, @@ -488,7 +488,7 @@ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_bv_sp_top_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_vs_pipe_bv_sp_top_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: A7XX_PIPE_BR Location: uSPTP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: PIPE_BR Location: uSPTP */ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_br_usptp_registers[] = { 0x0a800, 0x0a81b, 0x0a81e, 0x0a821, 0x0a823, 0x0a827, 0x0a830, 0x0a833, 0x0a836, 0x0a839, 0x0a83b, 0x0a85b, 0x0a85e, 0x0a861, 0x0a863, 0x0a867, @@ -498,7 +498,7 @@ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_br_usptp_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_vs_pipe_br_usptp_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: A7XX_PIPE_BV Location: uSPTP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_VS Pipeline: PIPE_BV Location: uSPTP */ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_bv_usptp_registers[] = { 0x0a800, 0x0a81b, 0x0a81e, 0x0a821, 0x0a823, 0x0a827, 0x0a830, 0x0a833, 0x0a836, 0x0a839, 0x0a83b, 0x0a85b, 0x0a85e, 0x0a861, 0x0a863, 0x0a867, @@ -508,7 +508,7 @@ static const u32 gen7_0_0_sp_cluster_sp_vs_pipe_bv_usptp_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_vs_pipe_bv_usptp_registers), 8)); -/* Block: TPL1 Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_BR */ +/* Block: TPL1 Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_BR */ static const u32 gen7_0_0_tpl1_cluster_sp_ps_pipe_br_registers[] = { 0x0b180, 0x0b183, 0x0b190, 0x0b195, 0x0b2c0, 0x0b2d5, 0x0b300, 0x0b307, 0x0b309, 0x0b309, 0x0b310, 0x0b310, @@ -516,35 +516,35 @@ static const u32 gen7_0_0_tpl1_cluster_sp_ps_pipe_br_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_tpl1_cluster_sp_ps_pipe_br_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_BV Location: HLSQ_STATE */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_BV Location: HLSQ_STATE */ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_bv_hlsq_state_registers[] = { 0x0ab00, 0x0ab02, 0x0ab0a, 0x0ab1b, 0x0ab20, 0x0ab20, 0x0ab40, 0x0abbf, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_ps_pipe_bv_hlsq_state_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_BV Location: SP_TOP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_BV Location: SP_TOP */ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_bv_sp_top_registers[] = { 0x0ab00, 0x0ab00, 0x0ab02, 0x0ab02, 0x0ab0a, 0x0ab1b, 0x0ab20, 0x0ab20, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_ps_pipe_bv_sp_top_registers), 8)); -/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_BV Location: uSPTP */ +/* Block: SP Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_BV Location: uSPTP */ static const u32 gen7_0_0_sp_cluster_sp_ps_pipe_bv_usptp_registers[] = { 0x0ab00, 0x0ab02, 0x0ab21, 0x0ab22, 0x0ab40, 0x0abbf, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_cluster_sp_ps_pipe_bv_usptp_registers), 8)); -/* Block: TPL1 Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_BV */ +/* Block: TPL1 Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_BV */ static const u32 gen7_0_0_tpl1_cluster_sp_ps_pipe_bv_registers[] = { 0x0b300, 0x0b307, 0x0b309, 0x0b309, 0x0b310, 0x0b310, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_tpl1_cluster_sp_ps_pipe_bv_registers), 8)); -/* Block: TPL1 Cluster: A7XX_CLUSTER_SP_PS Pipeline: A7XX_PIPE_LPAC */ +/* Block: TPL1 Cluster: A7XX_CLUSTER_SP_PS Pipeline: PIPE_LPAC */ static const u32 gen7_0_0_tpl1_cluster_sp_ps_pipe_lpac_registers[] = { 0x0b180, 0x0b181, 0x0b300, 0x0b301, 0x0b307, 0x0b307, 0x0b309, 0x0b309, 0x0b310, 0x0b310, @@ -552,84 +552,84 @@ static const u32 gen7_0_0_tpl1_cluster_sp_ps_pipe_lpac_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_tpl1_cluster_sp_ps_pipe_lpac_registers), 8)); -/* Block: TPL1 Cluster: A7XX_CLUSTER_SP_VS Pipeline: A7XX_PIPE_BR */ +/* Block: TPL1 Cluster: A7XX_CLUSTER_SP_VS Pipeline: PIPE_BR */ static const u32 gen7_0_0_tpl1_cluster_sp_vs_pipe_br_registers[] = { 0x0b300, 0x0b307, 0x0b309, 0x0b309, 0x0b310, 0x0b310, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_tpl1_cluster_sp_vs_pipe_br_registers), 8)); -/* Block: TPL1 Cluster: A7XX_CLUSTER_SP_VS Pipeline: A7XX_PIPE_BV */ +/* Block: TPL1 Cluster: A7XX_CLUSTER_SP_VS Pipeline: PIPE_BV */ static const u32 gen7_0_0_tpl1_cluster_sp_vs_pipe_bv_registers[] = { 0x0b300, 0x0b307, 0x0b309, 0x0b309, 0x0b310, 0x0b310, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_tpl1_cluster_sp_vs_pipe_bv_registers), 8)); -/* Block: VFD Cluster: A7XX_CLUSTER_FE Pipeline: A7XX_PIPE_BR */ +/* Block: VFD Cluster: A7XX_CLUSTER_FE Pipeline: PIPE_BR */ static const u32 gen7_0_0_vfd_cluster_fe_pipe_br_registers[] = { 0x0a000, 0x0a009, 0x0a00e, 0x0a0ef, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_vfd_cluster_fe_pipe_br_registers), 8)); -/* Block: VFD Cluster: A7XX_CLUSTER_FE Pipeline: A7XX_PIPE_BV */ +/* Block: VFD Cluster: A7XX_CLUSTER_FE Pipeline: PIPE_BV */ static const u32 gen7_0_0_vfd_cluster_fe_pipe_bv_registers[] = { 0x0a000, 0x0a009, 0x0a00e, 0x0a0ef, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_vfd_cluster_fe_pipe_bv_registers), 8)); -/* Block: VPC Cluster: A7XX_CLUSTER_FE Pipeline: A7XX_PIPE_BR */ +/* Block: VPC Cluster: A7XX_CLUSTER_FE Pipeline: PIPE_BR */ static const u32 gen7_0_0_vpc_cluster_fe_pipe_br_registers[] = { 0x09300, 0x09307, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_vpc_cluster_fe_pipe_br_registers), 8)); -/* Block: VPC Cluster: A7XX_CLUSTER_FE Pipeline: A7XX_PIPE_BV */ +/* Block: VPC Cluster: A7XX_CLUSTER_FE Pipeline: PIPE_BV */ static const u32 gen7_0_0_vpc_cluster_fe_pipe_bv_registers[] = { 0x09300, 0x09307, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_vpc_cluster_fe_pipe_bv_registers), 8)); -/* Block: VPC Cluster: A7XX_CLUSTER_PC_VS Pipeline: A7XX_PIPE_BR */ +/* Block: VPC Cluster: A7XX_CLUSTER_PC_VS Pipeline: PIPE_BR */ static const u32 gen7_0_0_vpc_cluster_pc_vs_pipe_br_registers[] = { 0x09101, 0x0910c, 0x09300, 0x09307, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_vpc_cluster_pc_vs_pipe_br_registers), 8)); -/* Block: VPC Cluster: A7XX_CLUSTER_PC_VS Pipeline: A7XX_PIPE_BV */ +/* Block: VPC Cluster: A7XX_CLUSTER_PC_VS Pipeline: PIPE_BV */ static const u32 gen7_0_0_vpc_cluster_pc_vs_pipe_bv_registers[] = { 0x09101, 0x0910c, 0x09300, 0x09307, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_vpc_cluster_pc_vs_pipe_bv_registers), 8)); -/* Block: VPC Cluster: A7XX_CLUSTER_VPC_PS Pipeline: A7XX_PIPE_BR */ +/* Block: VPC Cluster: A7XX_CLUSTER_VPC_PS Pipeline: PIPE_BR */ static const u32 gen7_0_0_vpc_cluster_vpc_ps_pipe_br_registers[] = { 0x09200, 0x0920f, 0x09212, 0x09216, 0x09218, 0x09236, 0x09300, 0x09307, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_vpc_cluster_vpc_ps_pipe_br_registers), 8)); -/* Block: VPC Cluster: A7XX_CLUSTER_VPC_PS Pipeline: A7XX_PIPE_BV */ +/* Block: VPC Cluster: A7XX_CLUSTER_VPC_PS Pipeline: PIPE_BV */ static const u32 gen7_0_0_vpc_cluster_vpc_ps_pipe_bv_registers[] = { 0x09200, 0x0920f, 0x09212, 0x09216, 0x09218, 0x09236, 0x09300, 0x09307, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_vpc_cluster_vpc_ps_pipe_bv_registers), 8)); -/* Block: SP Cluster: noncontext Pipeline: A7XX_PIPE_BR Location: HLSQ_STATE */ +/* Block: SP Cluster: noncontext Pipeline: PIPE_BR Location: HLSQ_STATE */ static const u32 gen7_0_0_sp_noncontext_pipe_br_hlsq_state_registers[] = { 0x0ae52, 0x0ae52, 0x0ae60, 0x0ae67, 0x0ae69, 0x0ae73, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_noncontext_pipe_br_hlsq_state_registers), 8)); -/* Block: SP Cluster: noncontext Pipeline: A7XX_PIPE_BR Location: SP_TOP */ +/* Block: SP Cluster: noncontext Pipeline: PIPE_BR Location: SP_TOP */ static const u32 gen7_0_0_sp_noncontext_pipe_br_sp_top_registers[] = { 0x0ae00, 0x0ae00, 0x0ae02, 0x0ae04, 0x0ae06, 0x0ae09, 0x0ae0c, 0x0ae0c, 0x0ae0f, 0x0ae0f, 0x0ae28, 0x0ae2b, 0x0ae35, 0x0ae35, 0x0ae3a, 0x0ae3f, @@ -638,7 +638,7 @@ static const u32 gen7_0_0_sp_noncontext_pipe_br_sp_top_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_noncontext_pipe_br_sp_top_registers), 8)); -/* Block: SP Cluster: noncontext Pipeline: A7XX_PIPE_BR Location: uSPTP */ +/* Block: SP Cluster: noncontext Pipeline: PIPE_BR Location: uSPTP */ static const u32 gen7_0_0_sp_noncontext_pipe_br_usptp_registers[] = { 0x0ae00, 0x0ae00, 0x0ae02, 0x0ae04, 0x0ae06, 0x0ae09, 0x0ae0c, 0x0ae0c, 0x0ae0f, 0x0ae0f, 0x0ae30, 0x0ae32, 0x0ae35, 0x0ae35, 0x0ae3a, 0x0ae3b, @@ -647,36 +647,43 @@ static const u32 gen7_0_0_sp_noncontext_pipe_br_usptp_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_noncontext_pipe_br_usptp_registers), 8)); -/* Block: SP Cluster: noncontext Pipeline: A7XX_PIPE_LPAC Location: HLSQ_STATE */ +/* Block: SP Cluster: noncontext Pipeline: PIPE_LPAC Location: HLSQ_STATE */ static const u32 gen7_0_0_sp_noncontext_pipe_lpac_hlsq_state_registers[] = { 0x0af88, 0x0af8a, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_noncontext_pipe_lpac_hlsq_state_registers), 8)); -/* Block: SP Cluster: noncontext Pipeline: A7XX_PIPE_LPAC Location: SP_TOP */ +/* Block: SP Cluster: noncontext Pipeline: PIPE_LPAC Location: SP_TOP */ static const u32 gen7_0_0_sp_noncontext_pipe_lpac_sp_top_registers[] = { 0x0af80, 0x0af84, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_noncontext_pipe_lpac_sp_top_registers), 8)); -/* Block: SP Cluster: noncontext Pipeline: A7XX_PIPE_LPAC Location: uSPTP */ +/* Block: SP Cluster: noncontext Pipeline: PIPE_LPAC Location: uSPTP */ static const u32 gen7_0_0_sp_noncontext_pipe_lpac_usptp_registers[] = { 0x0af80, 0x0af84, 0x0af90, 0x0af92, UINT_MAX, UINT_MAX, }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_sp_noncontext_pipe_lpac_usptp_registers), 8)); -/* Block: TPl1 Cluster: noncontext Pipeline: A7XX_PIPE_BR */ -static const u32 gen7_0_0_tpl1_noncontext_pipe_br_registers[] = { +/* Block: TPl1 Cluster: noncontext Pipeline: PIPE_NONE */ +static const u32 gen7_0_0_tpl1_noncontext_pipe_none_registers[] = { 0x0b600, 0x0b600, 0x0b602, 0x0b602, 0x0b604, 0x0b604, 0x0b608, 0x0b60c, 0x0b60f, 0x0b621, 0x0b630, 0x0b633, UINT_MAX, UINT_MAX, }; +static_assert(IS_ALIGNED(sizeof(gen7_0_0_tpl1_noncontext_pipe_none_registers), 8)); + +/* Block: TPl1 Cluster: noncontext Pipeline: PIPE_BR */ +static const u32 gen7_0_0_tpl1_noncontext_pipe_br_registers[] = { + 0x0b600, 0x0b600, + UINT_MAX, UINT_MAX, +}; static_assert(IS_ALIGNED(sizeof(gen7_0_0_tpl1_noncontext_pipe_br_registers), 8)); -/* Block: TPl1 Cluster: noncontext Pipeline: A7XX_PIPE_LPAC */ +/* Block: TPl1 Cluster: noncontext Pipeline: PIPE_LPAC */ static const u32 gen7_0_0_tpl1_noncontext_pipe_lpac_registers[] = { 0x0b780, 0x0b780, UINT_MAX, UINT_MAX, @@ -684,184 +691,184 @@ static const u32 gen7_0_0_tpl1_noncontext_pipe_lpac_registers[] = { static_assert(IS_ALIGNED(sizeof(gen7_0_0_tpl1_noncontext_pipe_lpac_registers), 8)); static const struct gen7_sel_reg gen7_0_0_rb_rac_sel = { - .host_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_HOST, - .cd_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, + .host_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_HOST, + .cd_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, .val = 0x0, }; static const struct gen7_sel_reg gen7_0_0_rb_rbp_sel = { - .host_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_HOST, - .cd_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, + .host_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_HOST, + .cd_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, .val = 0x9, }; -static struct gen7_cluster_registers gen7_0_0_clusters[] = { - { A7XX_CLUSTER_NONE, A7XX_PIPE_BR, STATE_NON_CONTEXT, +static const struct gen7_cluster_registers gen7_0_0_clusters[] = { + { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, gen7_0_0_noncontext_pipe_br_registers, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_BV, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_BV, STATE_NON_CONTEXT, gen7_0_0_noncontext_pipe_bv_registers, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_LPAC, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_LPAC, STATE_NON_CONTEXT, gen7_0_0_noncontext_pipe_lpac_registers, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_BR, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, gen7_0_0_noncontext_rb_rac_pipe_br_registers, &gen7_0_0_rb_rac_sel, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_BR, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, gen7_0_0_noncontext_rb_rbp_pipe_br_registers, &gen7_0_0_rb_rbp_sel, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_GRAS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_gras_cluster_gras_pipe_br_registers, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_GRAS, PIPE_BV, STATE_FORCE_CTXT_0, gen7_0_0_gras_cluster_gras_pipe_bv_registers, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_GRAS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_gras_cluster_gras_pipe_br_registers, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_GRAS, PIPE_BV, STATE_FORCE_CTXT_1, gen7_0_0_gras_cluster_gras_pipe_bv_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_pc_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_0, gen7_0_0_pc_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_pc_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_1, gen7_0_0_pc_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_rb_rac_cluster_ps_pipe_br_registers, &gen7_0_0_rb_rac_sel, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_rb_rac_cluster_ps_pipe_br_registers, &gen7_0_0_rb_rac_sel, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_rb_rbp_cluster_ps_pipe_br_registers, &gen7_0_0_rb_rbp_sel, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_rb_rbp_cluster_ps_pipe_br_registers, &gen7_0_0_rb_rbp_sel, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_vfd_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_0, gen7_0_0_vfd_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_vfd_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_1, gen7_0_0_vfd_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PC_VS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_pc_vs_pipe_br_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PC_VS, PIPE_BV, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_pc_vs_pipe_bv_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PC_VS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_pc_vs_pipe_br_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PC_VS, PIPE_BV, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_pc_vs_pipe_bv_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_VPC_PS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_vpc_ps_pipe_br_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_VPC_PS, PIPE_BV, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_vpc_ps_pipe_bv_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_VPC_PS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_vpc_ps_pipe_br_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_VPC_PS, PIPE_BV, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_vpc_ps_pipe_bv_registers, }, }; -static struct gen7_sptp_cluster_registers gen7_0_0_sptp_clusters[] = { - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_STATE, +static const struct gen7_sptp_cluster_registers gen7_0_0_sptp_clusters[] = { + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, gen7_0_0_sp_noncontext_pipe_br_hlsq_state_registers, 0xae00 }, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_SP_TOP, gen7_0_0_sp_noncontext_pipe_br_sp_top_registers, 0xae00 }, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_USPTP, gen7_0_0_sp_noncontext_pipe_br_usptp_registers, 0xae00 }, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_LPAC, 0, A7XX_HLSQ_STATE, gen7_0_0_sp_noncontext_pipe_lpac_hlsq_state_registers, 0xaf80 }, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_LPAC, 0, A7XX_SP_TOP, gen7_0_0_sp_noncontext_pipe_lpac_sp_top_registers, 0xaf80 }, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_0_0_sp_noncontext_pipe_lpac_usptp_registers, 0xaf80 }, - { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, PIPE_BR, 0, A7XX_USPTP, gen7_0_0_tpl1_noncontext_pipe_br_registers, 0xb600 }, - { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_0_0_tpl1_noncontext_pipe_lpac_registers, 0xb780 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_HLSQ_DP, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_SP_TOP, gen7_0_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_0_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_HLSQ_STATE, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_HLSQ_DP, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_SP_TOP, gen7_0_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_0_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_HLSQ_STATE, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_HLSQ_DP, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_SP_TOP, gen7_0_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_USPTP, gen7_0_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_HLSQ_STATE, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_HLSQ_DP, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_SP_TOP, gen7_0_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_USPTP, gen7_0_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_HLSQ_STATE, gen7_0_0_sp_cluster_sp_ps_pipe_lpac_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_HLSQ_DP, gen7_0_0_sp_cluster_sp_ps_pipe_lpac_hlsq_dp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_SP_TOP, gen7_0_0_sp_cluster_sp_ps_pipe_lpac_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_0_0_sp_cluster_sp_ps_pipe_lpac_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, gen7_0_0_sp_cluster_sp_vs_pipe_br_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_HLSQ_STATE, gen7_0_0_sp_cluster_sp_vs_pipe_bv_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_SP_TOP, gen7_0_0_sp_cluster_sp_vs_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_SP_TOP, gen7_0_0_sp_cluster_sp_vs_pipe_bv_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_0_0_sp_cluster_sp_vs_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_USPTP, gen7_0_0_sp_cluster_sp_vs_pipe_bv_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_HLSQ_STATE, gen7_0_0_sp_cluster_sp_vs_pipe_br_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_HLSQ_STATE, gen7_0_0_sp_cluster_sp_vs_pipe_bv_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_SP_TOP, gen7_0_0_sp_cluster_sp_vs_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_SP_TOP, gen7_0_0_sp_cluster_sp_vs_pipe_bv_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_0_0_sp_cluster_sp_vs_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_USPTP, gen7_0_0_sp_cluster_sp_vs_pipe_bv_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_ps_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_ps_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_ps_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_ps_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_ps_pipe_lpac_registers, 0xb000 }, - { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_vs_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_vs_pipe_bv_registers, 0xb000 }, - { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_vs_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_vs_pipe_bv_registers, 0xb000 }, }; @@ -914,7 +921,7 @@ static const u32 gen7_0_0_dpm_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_0_0_dpm_registers), 8)); -static struct gen7_reg_list gen7_0_0_reg_list[] = { +static const struct gen7_reg_list gen7_0_0_reg_list[] = { { gen7_0_0_gpu_registers, NULL }, { gen7_0_0_cx_misc_registers, NULL }, { gen7_0_0_dpm_registers, NULL }, diff --git a/drivers/gpu/drm/msm/adreno/adreno_gen7_2_0_snapshot.h b/drivers/gpu/drm/msm/adreno/adreno_gen7_2_0_snapshot.h index 6f8ad50f32ce..7897622ea6f7 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gen7_2_0_snapshot.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gen7_2_0_snapshot.h @@ -95,88 +95,88 @@ static const u32 gen7_2_0_debugbus_blocks[] = { A7XX_DBGBUS_CCHE_2, }; -static struct gen7_shader_block gen7_2_0_shader_blocks[] = { - {A7XX_TP0_TMO_DATA, 0x200, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_TP0_SMO_DATA, 0x80, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_TP0_MIPMAP_BASE_DATA, 0x3c0, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_INST_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_INST_DATA_1, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_0_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_1_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_2_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_3_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_4_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_5_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_6_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_7_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_CB_RAM, 0x390, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_13_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_14_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_INST_TAG, 0xc0, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_INST_DATA_2, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_TMO_TAG, 0x80, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_SMO_TAG, 0x80, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_STATE_DATA, 0x40, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_HWAVE_RAM, 0x100, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_L0_INST_BUF, 0x50, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_8_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_9_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_10_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_11_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_SP_LB_12_DATA, 0x800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP}, - {A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x300, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x300, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CPS_BE_CTXT_BUF_RAM, 0x300, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CVS_RAM, 0x1c0, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CVS_RAM, 0x1c0, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CPS_RAM, 0x300, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CPS_RAM, 0x180, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x40, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x40, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x40, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x40, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x10, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x10, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CVS_MISC_RAM, 0x280, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CVS_MISC_RAM, 0x280, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_MISC_RAM, 0x800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_MISC_RAM, 0x200, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_MISC_RAM_1, 0x1c0, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM, 0x800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM, 0x800, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM, 0x200, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x64, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x38, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x64, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x10, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x800, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x800, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INST_RAM_1, 0x800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_STPROC_META, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_BV_BE_META, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_BV_BE_META, 0x10, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_DATAPATH_META, 0x20, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_FRONTEND_META, 0x80, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_FRONTEND_META, 0x80, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_FRONTEND_META, 0x80, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_INDIRECT_META, 0x10, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE}, - {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE}, +static const struct gen7_shader_block gen7_2_0_shader_blocks[] = { + {A7XX_TP0_TMO_DATA, 0x200, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_TP0_SMO_DATA, 0x80, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_TP0_MIPMAP_BASE_DATA, 0x3c0, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_INST_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_INST_DATA_1, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_0_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_1_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_2_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_3_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_4_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_5_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_6_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_7_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_CB_RAM, 0x390, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_13_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_14_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_INST_TAG, 0xc0, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_INST_DATA_2, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_TMO_TAG, 0x80, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_SMO_TAG, 0x80, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_STATE_DATA, 0x40, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_HWAVE_RAM, 0x100, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_L0_INST_BUF, 0x50, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_8_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_9_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_10_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_11_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_SP_LB_12_DATA, 0x800, 6, 2, PIPE_BR, A7XX_USPTP}, + {A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_BE_CTXT_BUF_RAM_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x300, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x300, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CPS_BE_CTXT_BUF_RAM, 0x300, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CVS_RAM, 0x1c0, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CVS_RAM, 0x1c0, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CPS_RAM, 0x300, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CPS_RAM, 0x180, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x40, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x40, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x40, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x40, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x10, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x10, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CVS_MISC_RAM, 0x280, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CVS_MISC_RAM, 0x280, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_MISC_RAM, 0x800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_MISC_RAM, 0x200, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_MISC_RAM_1, 0x1c0, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM, 0x800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM, 0x800, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM, 0x200, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x10, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x10, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM_TAG, 0x80, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x64, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x38, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x64, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x10, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x800, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x800, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INST_RAM_1, 0x800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_STPROC_META, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_BV_BE_META, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_BV_BE_META, 0x10, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_DATAPATH_META, 0x20, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_FRONTEND_META, 0x80, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_FRONTEND_META, 0x80, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_FRONTEND_META, 0x80, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_INDIRECT_META, 0x10, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, PIPE_BR, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, PIPE_BV, A7XX_HLSQ_STATE}, + {A7XX_HLSQ_BACKEND_META, 0x40, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE}, }; static const u32 gen7_2_0_gpu_registers[] = { @@ -478,180 +478,182 @@ static const u32 gen7_2_0_sp_noncontext_pipe_lpac_hlsq_state_registers[] = { static_assert(IS_ALIGNED(sizeof(gen7_2_0_sp_noncontext_pipe_lpac_hlsq_state_registers), 8)); static const struct gen7_sel_reg gen7_2_0_rb_rac_sel = { - .host_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_HOST, - .cd_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, + .host_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_HOST, + .cd_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, .val = 0x0, }; static const struct gen7_sel_reg gen7_2_0_rb_rbp_sel = { - .host_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_HOST, - .cd_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, + .host_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_HOST, + .cd_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, .val = 0x9, }; -static struct gen7_cluster_registers gen7_2_0_clusters[] = { - { A7XX_CLUSTER_NONE, A7XX_PIPE_BR, STATE_NON_CONTEXT, +static const struct gen7_cluster_registers gen7_2_0_clusters[] = { + { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, gen7_2_0_noncontext_pipe_br_registers, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_BV, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_BV, STATE_NON_CONTEXT, gen7_2_0_noncontext_pipe_bv_registers, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_LPAC, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_LPAC, STATE_NON_CONTEXT, gen7_0_0_noncontext_pipe_lpac_registers, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_BR, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, gen7_2_0_noncontext_rb_rac_pipe_br_registers, &gen7_2_0_rb_rac_sel, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_BR, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, gen7_2_0_noncontext_rb_rbp_pipe_br_registers, &gen7_2_0_rb_rbp_sel, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_GRAS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_2_0_gras_cluster_gras_pipe_br_registers, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_GRAS, PIPE_BV, STATE_FORCE_CTXT_0, gen7_2_0_gras_cluster_gras_pipe_bv_registers, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_GRAS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_2_0_gras_cluster_gras_pipe_br_registers, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_GRAS, PIPE_BV, STATE_FORCE_CTXT_1, gen7_2_0_gras_cluster_gras_pipe_bv_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_pc_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_0, gen7_0_0_pc_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_pc_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_1, gen7_0_0_pc_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_2_0_rb_rac_cluster_ps_pipe_br_registers, &gen7_2_0_rb_rac_sel, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_2_0_rb_rac_cluster_ps_pipe_br_registers, &gen7_2_0_rb_rac_sel, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_rb_rbp_cluster_ps_pipe_br_registers, &gen7_2_0_rb_rbp_sel, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_rb_rbp_cluster_ps_pipe_br_registers, &gen7_2_0_rb_rbp_sel, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_vfd_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_0, gen7_0_0_vfd_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_vfd_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_1, gen7_0_0_vfd_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_fe_pipe_br_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_fe_pipe_bv_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PC_VS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_pc_vs_pipe_br_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PC_VS, PIPE_BV, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_pc_vs_pipe_bv_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PC_VS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_pc_vs_pipe_br_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PC_VS, PIPE_BV, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_pc_vs_pipe_bv_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_VPC_PS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_vpc_ps_pipe_br_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_VPC_PS, PIPE_BV, STATE_FORCE_CTXT_0, gen7_0_0_vpc_cluster_vpc_ps_pipe_bv_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_VPC_PS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_vpc_ps_pipe_br_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_VPC_PS, PIPE_BV, STATE_FORCE_CTXT_1, gen7_0_0_vpc_cluster_vpc_ps_pipe_bv_registers, }, }; -static struct gen7_sptp_cluster_registers gen7_2_0_sptp_clusters[] = { - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_STATE, +static const struct gen7_sptp_cluster_registers gen7_2_0_sptp_clusters[] = { + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, gen7_0_0_sp_noncontext_pipe_br_hlsq_state_registers, 0xae00 }, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_SP_TOP, gen7_0_0_sp_noncontext_pipe_br_sp_top_registers, 0xae00 }, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_USPTP, gen7_0_0_sp_noncontext_pipe_br_usptp_registers, 0xae00 }, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_LPAC, 0, A7XX_HLSQ_STATE, gen7_2_0_sp_noncontext_pipe_lpac_hlsq_state_registers, 0xaf80 }, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_LPAC, 0, A7XX_SP_TOP, gen7_0_0_sp_noncontext_pipe_lpac_sp_top_registers, 0xaf80 }, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_0_0_sp_noncontext_pipe_lpac_usptp_registers, 0xaf80 }, - { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, PIPE_BR, 0, A7XX_USPTP, gen7_0_0_tpl1_noncontext_pipe_br_registers, 0xb600 }, - { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, PIPE_NONE, 0, A7XX_USPTP, + gen7_0_0_tpl1_noncontext_pipe_none_registers, 0xb600 }, + { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_0_0_tpl1_noncontext_pipe_lpac_registers, 0xb780 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, gen7_2_0_sp_cluster_sp_ps_pipe_br_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_HLSQ_DP, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_SP_TOP, gen7_2_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_2_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_HLSQ_STATE, gen7_2_0_sp_cluster_sp_ps_pipe_br_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_HLSQ_DP, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_SP_TOP, gen7_2_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_2_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_HLSQ_DP, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_HLSQ_DP, gen7_0_0_sp_cluster_sp_ps_pipe_br_hlsq_dp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_SP_TOP, gen7_2_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_USPTP, gen7_2_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_SP_TOP, gen7_2_0_sp_cluster_sp_ps_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_USPTP, gen7_2_0_sp_cluster_sp_ps_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_HLSQ_STATE, gen7_2_0_sp_cluster_sp_ps_pipe_lpac_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_HLSQ_DP, gen7_0_0_sp_cluster_sp_ps_pipe_lpac_hlsq_dp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_SP_TOP, gen7_2_0_sp_cluster_sp_ps_pipe_lpac_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_2_0_sp_cluster_sp_ps_pipe_lpac_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, gen7_2_0_sp_cluster_sp_vs_pipe_br_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_HLSQ_STATE, gen7_2_0_sp_cluster_sp_vs_pipe_bv_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_SP_TOP, gen7_2_0_sp_cluster_sp_vs_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_SP_TOP, gen7_2_0_sp_cluster_sp_vs_pipe_bv_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_2_0_sp_cluster_sp_vs_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_USPTP, gen7_2_0_sp_cluster_sp_vs_pipe_bv_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_HLSQ_STATE, gen7_2_0_sp_cluster_sp_vs_pipe_br_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_HLSQ_STATE, gen7_2_0_sp_cluster_sp_vs_pipe_bv_hlsq_state_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_SP_TOP, gen7_2_0_sp_cluster_sp_vs_pipe_br_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_SP_TOP, gen7_2_0_sp_cluster_sp_vs_pipe_bv_sp_top_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_2_0_sp_cluster_sp_vs_pipe_br_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_USPTP, gen7_2_0_sp_cluster_sp_vs_pipe_bv_usptp_registers, 0xa800 }, - { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_ps_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_ps_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_ps_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_ps_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_TP0_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_ps_pipe_lpac_registers, 0xb000 }, - { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_vs_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_vs_pipe_bv_registers, 0xb000 }, - { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_vs_pipe_br_registers, 0xb000 }, - { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_TP0_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_USPTP, gen7_0_0_tpl1_cluster_sp_vs_pipe_bv_registers, 0xb000 }, }; @@ -737,7 +739,7 @@ static const u32 gen7_2_0_dpm_registers[] = { }; static_assert(IS_ALIGNED(sizeof(gen7_2_0_dpm_registers), 8)); -static struct gen7_reg_list gen7_2_0_reg_list[] = { +static const struct gen7_reg_list gen7_2_0_reg_list[] = { { gen7_2_0_gpu_registers, NULL }, { gen7_2_0_cx_misc_registers, NULL }, { gen7_2_0_dpm_registers, NULL }, diff --git a/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h b/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h index 9a327d543f27..20125d1aa21d 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h @@ -117,98 +117,98 @@ static const u32 gen7_9_0_cx_debugbus_blocks[] = { A7XX_DBGBUS_GBIF_CX, }; -static struct gen7_shader_block gen7_9_0_shader_blocks[] = { - { A7XX_TP0_TMO_DATA, 0x0200, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_TP0_SMO_DATA, 0x0080, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_TP0_MIPMAP_BASE_DATA, 0x03C0, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_INST_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_INST_DATA_1, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_0_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_1_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_2_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_3_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_4_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_5_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_6_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_7_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_CB_RAM, 0x0390, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_13_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_14_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_INST_TAG, 0x00C0, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_INST_DATA_2, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_TMO_TAG, 0x0080, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_SMO_TAG, 0x0080, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_STATE_DATA, 0x0040, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_HWAVE_RAM, 0x0100, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_L0_INST_BUF, 0x0050, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_8_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_9_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_10_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_11_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_SP_LB_12_DATA, 0x0800, 6, 2, A7XX_PIPE_BR, A7XX_USPTP }, - { A7XX_HLSQ_DATAPATH_DSTR_META, 0x0010, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_DATAPATH_DSTR_META, 0x0010, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_L2STC_TAG_RAM, 0x0200, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_L2STC_INFO_CMD, 0x0474, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x0080, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x0080, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CPS_BE_CTXT_BUF_RAM_TAG, 0x0080, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x0400, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x0400, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_CPS_BE_CTXT_BUF_RAM, 0x0400, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CHUNK_CVS_RAM, 0x01C0, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CHUNK_CVS_RAM, 0x01C0, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CHUNK_CPS_RAM, 0x0300, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CHUNK_CPS_RAM, 0x0180, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x0040, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x0040, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x0040, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x0040, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x0010, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x0010, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x0010, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x0010, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CVS_MISC_RAM, 0x0540, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CVS_MISC_RAM, 0x0540, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CPS_MISC_RAM, 0x0640, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CPS_MISC_RAM, 0x00B0, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CPS_MISC_RAM_1, 0x0800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_INST_RAM, 0x0800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_INST_RAM, 0x0800, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_INST_RAM, 0x0200, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x0800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x0800, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x0800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x0800, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x0050, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x0050, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x0050, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x0008, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_INST_RAM_TAG, 0x0014, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_INST_RAM_TAG, 0x0010, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_INST_RAM_TAG, 0x0004, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x0040, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x0040, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x0040, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x0020, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_LOCAL_MISC_RAM, 0x03C0, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_LOCAL_MISC_RAM, 0x0280, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_LOCAL_MISC_RAM, 0x0050, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_LOCAL_MISC_RAM_TAG, 0x0010, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_GFX_LOCAL_MISC_RAM_TAG, 0x0008, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_INST_RAM_1, 0x0800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_STPROC_META, 0x0010, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_BV_BE_META, 0x0018, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_BV_BE_META, 0x0018, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_INST_RAM_2, 0x0800, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_DATAPATH_META, 0x0020, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_FRONTEND_META, 0x0080, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_FRONTEND_META, 0x0080, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_FRONTEND_META, 0x0080, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_INDIRECT_META, 0x0010, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_BACKEND_META, 0x0040, 1, 1, A7XX_PIPE_BR, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_BACKEND_META, 0x0040, 1, 1, A7XX_PIPE_BV, A7XX_HLSQ_STATE }, - { A7XX_HLSQ_BACKEND_META, 0x0040, 1, 1, A7XX_PIPE_LPAC, A7XX_HLSQ_STATE }, +static const struct gen7_shader_block gen7_9_0_shader_blocks[] = { + { A7XX_TP0_TMO_DATA, 0x0200, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_TP0_SMO_DATA, 0x0080, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_TP0_MIPMAP_BASE_DATA, 0x03C0, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_INST_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_INST_DATA_1, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_0_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_1_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_2_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_3_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_4_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_5_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_6_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_7_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_CB_RAM, 0x0390, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_13_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_14_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_INST_TAG, 0x00C0, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_INST_DATA_2, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_TMO_TAG, 0x0080, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_SMO_TAG, 0x0080, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_STATE_DATA, 0x0040, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_HWAVE_RAM, 0x0100, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_L0_INST_BUF, 0x0050, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_8_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_9_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_10_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_11_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_SP_LB_12_DATA, 0x0800, 6, 2, PIPE_BR, A7XX_USPTP }, + { A7XX_HLSQ_DATAPATH_DSTR_META, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_DATAPATH_DSTR_META, 0x0010, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_L2STC_TAG_RAM, 0x0200, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_L2STC_INFO_CMD, 0x0474, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x0080, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG, 0x0080, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CPS_BE_CTXT_BUF_RAM_TAG, 0x0080, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x0400, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM, 0x0400, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_CPS_BE_CTXT_BUF_RAM, 0x0400, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CHUNK_CVS_RAM, 0x01C0, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CHUNK_CVS_RAM, 0x01C0, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CHUNK_CPS_RAM, 0x0300, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CHUNK_CPS_RAM, 0x0180, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x0040, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x0040, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x0040, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x0040, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x0010, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x0010, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CVS_MISC_RAM, 0x0540, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CVS_MISC_RAM, 0x0540, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CPS_MISC_RAM, 0x0640, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CPS_MISC_RAM, 0x00B0, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CPS_MISC_RAM_1, 0x0800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_INST_RAM, 0x0800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_INST_RAM, 0x0800, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_INST_RAM, 0x0200, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x0800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_CVS_CONST_RAM, 0x0800, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x0800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_CPS_CONST_RAM, 0x0800, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x0050, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CVS_MISC_RAM_TAG, 0x0050, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x0050, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_CPS_MISC_RAM_TAG, 0x0008, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_INST_RAM_TAG, 0x0014, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_INST_RAM_TAG, 0x0010, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_INST_RAM_TAG, 0x0004, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x0040, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0x0040, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x0040, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x0020, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_LOCAL_MISC_RAM, 0x03C0, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_LOCAL_MISC_RAM, 0x0280, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_LOCAL_MISC_RAM, 0x0050, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_LOCAL_MISC_RAM_TAG, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_GFX_LOCAL_MISC_RAM_TAG, 0x0008, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_INST_RAM_1, 0x0800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_STPROC_META, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_BV_BE_META, 0x0018, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_BV_BE_META, 0x0018, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_INST_RAM_2, 0x0800, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_DATAPATH_META, 0x0020, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_FRONTEND_META, 0x0080, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_FRONTEND_META, 0x0080, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_FRONTEND_META, 0x0080, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_INDIRECT_META, 0x0010, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_BACKEND_META, 0x0040, 1, 1, PIPE_BR, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_BACKEND_META, 0x0040, 1, 1, PIPE_BV, A7XX_HLSQ_STATE }, + { A7XX_HLSQ_BACKEND_META, 0x0040, 1, 1, PIPE_LPAC, A7XX_HLSQ_STATE }, }; /* @@ -226,7 +226,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_pre_crashdumper_gpu_registers), 8)); * Block : ['BROADCAST', 'CP', 'GRAS', 'GXCLKCTL'] * Block : ['PC', 'RBBM', 'RDVM', 'UCHE'] * Block : ['VFD', 'VPC', 'VSC'] - * Pipeline: A7XX_PIPE_NONE + * Pipeline: PIPE_NONE * pairs : 196 (Regs:1778) */ static const u32 gen7_9_0_gpu_registers[] = { @@ -290,7 +290,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_gxclkctl_registers), 8)); /* * Block : ['GMUAO', 'GMUCX', 'GMUCX_RAM'] - * Pipeline: A7XX_PIPE_NONE + * Pipeline: PIPE_NONE * pairs : 134 (Regs:429) */ static const u32 gen7_9_0_gmu_registers[] = { @@ -334,7 +334,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_gmu_registers), 8)); /* * Block : ['GMUGX'] - * Pipeline: A7XX_PIPE_NONE + * Pipeline: PIPE_NONE * pairs : 44 (Regs:454) */ static const u32 gen7_9_0_gmugx_registers[] = { @@ -355,7 +355,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_gmugx_registers), 8)); /* * Block : ['CX_MISC'] - * Pipeline: A7XX_PIPE_NONE + * Pipeline: PIPE_NONE * pairs : 7 (Regs:56) */ static const u32 gen7_9_0_cx_misc_registers[] = { @@ -367,7 +367,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_cx_misc_registers), 8)); /* * Block : ['DBGC'] - * Pipeline: A7XX_PIPE_NONE + * Pipeline: PIPE_NONE * pairs : 19 (Regs:155) */ static const u32 gen7_9_0_dbgc_registers[] = { @@ -382,7 +382,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_dbgc_registers), 8)); /* * Block : ['CX_DBGC'] - * Pipeline: A7XX_PIPE_NONE + * Pipeline: PIPE_NONE * pairs : 7 (Regs:75) */ static const u32 gen7_9_0_cx_dbgc_registers[] = { @@ -396,7 +396,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_cx_dbgc_registers), 8)); * Block : ['BROADCAST', 'CP', 'CX_DBGC', 'CX_MISC', 'DBGC', 'GBIF'] * Block : ['GMUAO', 'GMUCX', 'GMUGX', 'GRAS', 'GXCLKCTL', 'PC'] * Block : ['RBBM', 'RDVM', 'UCHE', 'VFD', 'VPC', 'VSC'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_NONE * pairs : 29 (Regs:573) */ @@ -417,7 +417,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_pipe_br_registers), 8)); * Block : ['BROADCAST', 'CP', 'CX_DBGC', 'CX_MISC', 'DBGC', 'GBIF'] * Block : ['GMUAO', 'GMUCX', 'GMUGX', 'GRAS', 'GXCLKCTL', 'PC'] * Block : ['RBBM', 'RDVM', 'UCHE', 'VFD', 'VPC', 'VSC'] - * Pipeline: A7XX_PIPE_BV + * Pipeline: PIPE_BV * Cluster : A7XX_CLUSTER_NONE * pairs : 29 (Regs:573) */ @@ -438,7 +438,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_pipe_bv_registers), 8)); * Block : ['BROADCAST', 'CP', 'CX_DBGC', 'CX_MISC', 'DBGC', 'GBIF'] * Block : ['GMUAO', 'GMUCX', 'GMUGX', 'GRAS', 'GXCLKCTL', 'PC'] * Block : ['RBBM', 'RDVM', 'UCHE', 'VFD', 'VPC', 'VSC'] - * Pipeline: A7XX_PIPE_LPAC + * Pipeline: PIPE_LPAC * Cluster : A7XX_CLUSTER_NONE * pairs : 2 (Regs:7) */ @@ -450,7 +450,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_pipe_lpac_registers), 8)); /* * Block : ['RB'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_NONE * pairs : 5 (Regs:37) */ @@ -463,7 +463,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_rb_pipe_br_rac_registers), /* * Block : ['RB'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_NONE * pairs : 15 (Regs:66) */ @@ -478,7 +478,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_rb_pipe_br_rbp_registers), /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_NONE * Location: A7XX_HLSQ_STATE * pairs : 4 (Regs:28) @@ -491,7 +491,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_sp_pipe_br_hlsq_state_regis /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_NONE * Location: A7XX_SP_TOP * pairs : 10 (Regs:61) @@ -506,7 +506,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_sp_pipe_br_sp_top_registers /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_NONE * Location: A7XX_USPTP * pairs : 12 (Regs:62) @@ -521,7 +521,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_sp_pipe_br_usptp_registers) /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_NONE * Location: A7XX_HLSQ_DP_STR * pairs : 2 (Regs:5) @@ -534,7 +534,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_sp_pipe_br_hlsq_dp_str_regi /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_LPAC + * Pipeline: PIPE_LPAC * Cluster : A7XX_CLUSTER_NONE * Location: A7XX_HLSQ_STATE * pairs : 1 (Regs:5) @@ -547,7 +547,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_sp_pipe_lpac_hlsq_state_reg /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_LPAC + * Pipeline: PIPE_LPAC * Cluster : A7XX_CLUSTER_NONE * Location: A7XX_SP_TOP * pairs : 1 (Regs:6) @@ -560,7 +560,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_sp_pipe_lpac_sp_top_registe /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_LPAC + * Pipeline: PIPE_LPAC * Cluster : A7XX_CLUSTER_NONE * Location: A7XX_USPTP * pairs : 2 (Regs:9) @@ -573,7 +573,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_sp_pipe_lpac_usptp_register /* * Block : ['TPL1'] - * Pipeline: A7XX_PIPE_NONE + * Pipeline: PIPE_NONE * Cluster : A7XX_CLUSTER_NONE * Location: A7XX_USPTP * pairs : 5 (Regs:29) @@ -587,7 +587,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_tpl1_pipe_none_usptp_regist /* * Block : ['TPL1'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_NONE * Location: A7XX_USPTP * pairs : 1 (Regs:1) @@ -600,7 +600,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_tpl1_pipe_br_usptp_register /* * Block : ['TPL1'] - * Pipeline: A7XX_PIPE_LPAC + * Pipeline: PIPE_LPAC * Cluster : A7XX_CLUSTER_NONE * Location: A7XX_USPTP * pairs : 1 (Regs:1) @@ -613,7 +613,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_non_context_tpl1_pipe_lpac_usptp_regist /* * Block : ['GRAS'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_GRAS * pairs : 14 (Regs:293) */ @@ -628,7 +628,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_gras_pipe_br_cluster_gras_registers), 8 /* * Block : ['GRAS'] - * Pipeline: A7XX_PIPE_BV + * Pipeline: PIPE_BV * Cluster : A7XX_CLUSTER_GRAS * pairs : 14 (Regs:293) */ @@ -643,7 +643,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_gras_pipe_bv_cluster_gras_registers), 8 /* * Block : ['PC'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_FE * pairs : 6 (Regs:31) */ @@ -656,7 +656,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_pc_pipe_br_cluster_fe_registers), 8)); /* * Block : ['PC'] - * Pipeline: A7XX_PIPE_BV + * Pipeline: PIPE_BV * Cluster : A7XX_CLUSTER_FE * pairs : 6 (Regs:31) */ @@ -669,7 +669,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_pc_pipe_bv_cluster_fe_registers), 8)); /* * Block : ['VFD'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_FE * pairs : 2 (Regs:236) */ @@ -681,7 +681,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_vfd_pipe_br_cluster_fe_registers), 8)); /* * Block : ['VFD'] - * Pipeline: A7XX_PIPE_BV + * Pipeline: PIPE_BV * Cluster : A7XX_CLUSTER_FE * pairs : 2 (Regs:236) */ @@ -693,7 +693,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_vfd_pipe_bv_cluster_fe_registers), 8)); /* * Block : ['VPC'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_FE * pairs : 2 (Regs:18) */ @@ -705,7 +705,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_vpc_pipe_br_cluster_fe_registers), 8)); /* * Block : ['VPC'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_PC_VS * pairs : 3 (Regs:30) */ @@ -717,7 +717,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_vpc_pipe_br_cluster_pc_vs_registers), 8 /* * Block : ['VPC'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_VPC_PS * pairs : 5 (Regs:76) */ @@ -730,7 +730,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_vpc_pipe_br_cluster_vpc_ps_registers), /* * Block : ['VPC'] - * Pipeline: A7XX_PIPE_BV + * Pipeline: PIPE_BV * Cluster : A7XX_CLUSTER_FE * pairs : 2 (Regs:18) */ @@ -742,7 +742,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_vpc_pipe_bv_cluster_fe_registers), 8)); /* * Block : ['VPC'] - * Pipeline: A7XX_PIPE_BV + * Pipeline: PIPE_BV * Cluster : A7XX_CLUSTER_PC_VS * pairs : 3 (Regs:30) */ @@ -754,7 +754,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_vpc_pipe_bv_cluster_pc_vs_registers), 8 /* * Block : ['VPC'] - * Pipeline: A7XX_PIPE_BV + * Pipeline: PIPE_BV * Cluster : A7XX_CLUSTER_VPC_PS * pairs : 5 (Regs:76) */ @@ -767,7 +767,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_vpc_pipe_bv_cluster_vpc_ps_registers), /* * Block : ['RB'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_PS * pairs : 39 (Regs:133) */ @@ -788,7 +788,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_rb_pipe_br_cluster_ps_rac_registers), 8 /* * Block : ['RB'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_PS * pairs : 34 (Regs:100) */ @@ -808,7 +808,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_rb_pipe_br_cluster_ps_rbp_registers), 8 /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_SP_VS * Location: A7XX_HLSQ_STATE * pairs : 29 (Regs:215) @@ -828,7 +828,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_br_cluster_sp_vs_hlsq_state_reg /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_SP_VS * Location: A7XX_SP_TOP * pairs : 22 (Regs:73) @@ -846,7 +846,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_br_cluster_sp_vs_sp_top_registe /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_SP_VS * Location: A7XX_USPTP * pairs : 16 (Regs:269) @@ -862,7 +862,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_br_cluster_sp_vs_usptp_register /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_SP_PS * Location: A7XX_HLSQ_STATE * pairs : 21 (Regs:334) @@ -880,7 +880,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_state_reg /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_SP_PS * Location: A7XX_HLSQ_DP * pairs : 3 (Regs:19) @@ -893,7 +893,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_dp_regist /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_SP_PS * Location: A7XX_SP_TOP * pairs : 18 (Regs:77) @@ -910,7 +910,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_br_cluster_sp_ps_sp_top_registe /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_SP_PS * Location: A7XX_USPTP * pairs : 17 (Regs:333) @@ -927,7 +927,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_br_cluster_sp_ps_usptp_register /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_SP_PS * Location: A7XX_HLSQ_DP_STR * pairs : 1 (Regs:6) @@ -940,7 +940,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_dp_str_re /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BV + * Pipeline: PIPE_BV * Cluster : A7XX_CLUSTER_SP_VS * Location: A7XX_HLSQ_STATE * pairs : 28 (Regs:213) @@ -959,7 +959,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_bv_cluster_sp_vs_hlsq_state_reg /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BV + * Pipeline: PIPE_BV * Cluster : A7XX_CLUSTER_SP_VS * Location: A7XX_SP_TOP * pairs : 21 (Regs:71) @@ -977,7 +977,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_bv_cluster_sp_vs_sp_top_registe /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_BV + * Pipeline: PIPE_BV * Cluster : A7XX_CLUSTER_SP_VS * Location: A7XX_USPTP * pairs : 16 (Regs:266) @@ -993,7 +993,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_bv_cluster_sp_vs_usptp_register /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_LPAC + * Pipeline: PIPE_LPAC * Cluster : A7XX_CLUSTER_SP_PS * Location: A7XX_HLSQ_STATE * pairs : 14 (Regs:299) @@ -1009,7 +1009,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_lpac_cluster_sp_ps_hlsq_state_r /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_LPAC + * Pipeline: PIPE_LPAC * Cluster : A7XX_CLUSTER_SP_PS * Location: A7XX_HLSQ_DP * pairs : 2 (Regs:13) @@ -1022,7 +1022,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_lpac_cluster_sp_ps_hlsq_dp_regi /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_LPAC + * Pipeline: PIPE_LPAC * Cluster : A7XX_CLUSTER_SP_PS * Location: A7XX_SP_TOP * pairs : 9 (Regs:34) @@ -1037,7 +1037,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_lpac_cluster_sp_ps_sp_top_regis /* * Block : ['SP'] - * Pipeline: A7XX_PIPE_LPAC + * Pipeline: PIPE_LPAC * Cluster : A7XX_CLUSTER_SP_PS * Location: A7XX_USPTP * pairs : 11 (Regs:279) @@ -1052,7 +1052,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_sp_pipe_lpac_cluster_sp_ps_usptp_regist /* * Block : ['TPL1'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_SP_VS * Location: A7XX_USPTP * pairs : 3 (Regs:10) @@ -1065,7 +1065,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_tpl1_pipe_br_cluster_sp_vs_usptp_regist /* * Block : ['TPL1'] - * Pipeline: A7XX_PIPE_BR + * Pipeline: PIPE_BR * Cluster : A7XX_CLUSTER_SP_PS * Location: A7XX_USPTP * pairs : 6 (Regs:42) @@ -1079,7 +1079,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_tpl1_pipe_br_cluster_sp_ps_usptp_regist /* * Block : ['TPL1'] - * Pipeline: A7XX_PIPE_BV + * Pipeline: PIPE_BV * Cluster : A7XX_CLUSTER_SP_VS * Location: A7XX_USPTP * pairs : 3 (Regs:10) @@ -1092,7 +1092,7 @@ static_assert(IS_ALIGNED(sizeof(gen7_9_0_tpl1_pipe_bv_cluster_sp_vs_usptp_regist /* * Block : ['TPL1'] - * Pipeline: A7XX_PIPE_LPAC + * Pipeline: PIPE_LPAC * Cluster : A7XX_CLUSTER_SP_PS * Location: A7XX_USPTP * pairs : 5 (Regs:7) @@ -1105,223 +1105,223 @@ static const u32 gen7_9_0_tpl1_pipe_lpac_cluster_sp_ps_usptp_registers[] = { static_assert(IS_ALIGNED(sizeof(gen7_9_0_tpl1_pipe_lpac_cluster_sp_ps_usptp_registers), 8)); static const struct gen7_sel_reg gen7_9_0_rb_rac_sel = { - .host_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_HOST, - .cd_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, + .host_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_HOST, + .cd_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, .val = 0, }; static const struct gen7_sel_reg gen7_9_0_rb_rbp_sel = { - .host_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_HOST, - .cd_reg = REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, + .host_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_HOST, + .cd_reg = REG_A6XX_RB_SUB_BLOCK_SEL_CNTL_CD, .val = 0x9, }; -static struct gen7_cluster_registers gen7_9_0_clusters[] = { - { A7XX_CLUSTER_NONE, A7XX_PIPE_BR, STATE_NON_CONTEXT, +static const struct gen7_cluster_registers gen7_9_0_clusters[] = { + { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, gen7_9_0_non_context_pipe_br_registers, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_BV, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_BV, STATE_NON_CONTEXT, gen7_9_0_non_context_pipe_bv_registers, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_LPAC, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_LPAC, STATE_NON_CONTEXT, gen7_9_0_non_context_pipe_lpac_registers, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_BR, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, gen7_9_0_non_context_rb_pipe_br_rac_registers, &gen7_9_0_rb_rac_sel, }, - { A7XX_CLUSTER_NONE, A7XX_PIPE_BR, STATE_NON_CONTEXT, + { A7XX_CLUSTER_NONE, PIPE_BR, STATE_NON_CONTEXT, gen7_9_0_non_context_rb_pipe_br_rbp_registers, &gen7_9_0_rb_rbp_sel, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_9_0_rb_pipe_br_cluster_ps_rac_registers, &gen7_9_0_rb_rac_sel, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_9_0_rb_pipe_br_cluster_ps_rac_registers, &gen7_9_0_rb_rac_sel, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_9_0_rb_pipe_br_cluster_ps_rbp_registers, &gen7_9_0_rb_rbp_sel, }, - { A7XX_CLUSTER_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_9_0_rb_pipe_br_cluster_ps_rbp_registers, &gen7_9_0_rb_rbp_sel, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_GRAS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_9_0_gras_pipe_br_cluster_gras_registers, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_GRAS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_9_0_gras_pipe_br_cluster_gras_registers, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_GRAS, PIPE_BV, STATE_FORCE_CTXT_0, gen7_9_0_gras_pipe_bv_cluster_gras_registers, }, - { A7XX_CLUSTER_GRAS, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_GRAS, PIPE_BV, STATE_FORCE_CTXT_1, gen7_9_0_gras_pipe_bv_cluster_gras_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, gen7_9_0_pc_pipe_br_cluster_fe_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, gen7_9_0_pc_pipe_br_cluster_fe_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_0, gen7_9_0_pc_pipe_bv_cluster_fe_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_1, gen7_9_0_pc_pipe_bv_cluster_fe_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, gen7_9_0_vfd_pipe_br_cluster_fe_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, gen7_9_0_vfd_pipe_br_cluster_fe_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_0, gen7_9_0_vfd_pipe_bv_cluster_fe_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_1, gen7_9_0_vfd_pipe_bv_cluster_fe_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_0, gen7_9_0_vpc_pipe_br_cluster_fe_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BR, STATE_FORCE_CTXT_1, gen7_9_0_vpc_pipe_br_cluster_fe_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PC_VS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_9_0_vpc_pipe_br_cluster_pc_vs_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PC_VS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_9_0_vpc_pipe_br_cluster_pc_vs_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_VPC_PS, PIPE_BR, STATE_FORCE_CTXT_0, gen7_9_0_vpc_pipe_br_cluster_vpc_ps_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BR, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_VPC_PS, PIPE_BR, STATE_FORCE_CTXT_1, gen7_9_0_vpc_pipe_br_cluster_vpc_ps_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_0, gen7_9_0_vpc_pipe_bv_cluster_fe_registers, }, - { A7XX_CLUSTER_FE, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_FE, PIPE_BV, STATE_FORCE_CTXT_1, gen7_9_0_vpc_pipe_bv_cluster_fe_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_PC_VS, PIPE_BV, STATE_FORCE_CTXT_0, gen7_9_0_vpc_pipe_bv_cluster_pc_vs_registers, }, - { A7XX_CLUSTER_PC_VS, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_PC_VS, PIPE_BV, STATE_FORCE_CTXT_1, gen7_9_0_vpc_pipe_bv_cluster_pc_vs_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BV, STATE_FORCE_CTXT_0, + { A7XX_CLUSTER_VPC_PS, PIPE_BV, STATE_FORCE_CTXT_0, gen7_9_0_vpc_pipe_bv_cluster_vpc_ps_registers, }, - { A7XX_CLUSTER_VPC_PS, A7XX_PIPE_BV, STATE_FORCE_CTXT_1, + { A7XX_CLUSTER_VPC_PS, PIPE_BV, STATE_FORCE_CTXT_1, gen7_9_0_vpc_pipe_bv_cluster_vpc_ps_registers, }, }; -static struct gen7_sptp_cluster_registers gen7_9_0_sptp_clusters[] = { - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_STATE, +static const struct gen7_sptp_cluster_registers gen7_9_0_sptp_clusters[] = { + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, gen7_9_0_non_context_sp_pipe_br_hlsq_state_registers, 0xae00}, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_SP_TOP, gen7_9_0_non_context_sp_pipe_br_sp_top_registers, 0xae00}, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_USPTP, gen7_9_0_non_context_sp_pipe_br_usptp_registers, 0xae00}, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_DP_STR, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_BR, 0, A7XX_HLSQ_DP_STR, gen7_9_0_non_context_sp_pipe_br_hlsq_dp_str_registers, 0xae00}, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_LPAC, 0, A7XX_HLSQ_STATE, gen7_9_0_non_context_sp_pipe_lpac_hlsq_state_registers, 0xaf80}, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_LPAC, 0, A7XX_SP_TOP, gen7_9_0_non_context_sp_pipe_lpac_sp_top_registers, 0xaf80}, - { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_SP_NCTX_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_9_0_non_context_sp_pipe_lpac_usptp_registers, 0xaf80}, - { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, A7XX_PIPE_NONE, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, PIPE_NONE, 0, A7XX_USPTP, gen7_9_0_non_context_tpl1_pipe_none_usptp_registers, 0xb600}, - { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, PIPE_BR, 0, A7XX_USPTP, gen7_9_0_non_context_tpl1_pipe_br_usptp_registers, 0xb600}, - { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_NONE, A7XX_TP0_NCTX_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_9_0_non_context_tpl1_pipe_lpac_usptp_registers, 0xb780}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, gen7_9_0_sp_pipe_br_cluster_sp_vs_hlsq_state_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_SP_TOP, gen7_9_0_sp_pipe_br_cluster_sp_vs_sp_top_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_9_0_sp_pipe_br_cluster_sp_vs_usptp_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_HLSQ_STATE, gen7_9_0_sp_pipe_bv_cluster_sp_vs_hlsq_state_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_SP_TOP, gen7_9_0_sp_pipe_bv_cluster_sp_vs_sp_top_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_USPTP, gen7_9_0_sp_pipe_bv_cluster_sp_vs_usptp_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_HLSQ_STATE, gen7_9_0_sp_pipe_br_cluster_sp_vs_hlsq_state_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_SP_TOP, gen7_9_0_sp_pipe_br_cluster_sp_vs_sp_top_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_9_0_sp_pipe_br_cluster_sp_vs_usptp_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_HLSQ_STATE, gen7_9_0_sp_pipe_bv_cluster_sp_vs_hlsq_state_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_SP_TOP, gen7_9_0_sp_pipe_bv_cluster_sp_vs_sp_top_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_USPTP, gen7_9_0_sp_pipe_bv_cluster_sp_vs_usptp_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_HLSQ_STATE, gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_state_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_HLSQ_DP, gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_dp_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_SP_TOP, gen7_9_0_sp_pipe_br_cluster_sp_ps_sp_top_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_9_0_sp_pipe_br_cluster_sp_ps_usptp_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_HLSQ_DP_STR, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_HLSQ_DP_STR, gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_dp_str_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_HLSQ_STATE, gen7_9_0_sp_pipe_lpac_cluster_sp_ps_hlsq_state_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_HLSQ_DP, gen7_9_0_sp_pipe_lpac_cluster_sp_ps_hlsq_dp_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_SP_TOP, gen7_9_0_sp_pipe_lpac_cluster_sp_ps_sp_top_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_9_0_sp_pipe_lpac_cluster_sp_ps_usptp_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_HLSQ_STATE, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_HLSQ_STATE, gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_state_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_HLSQ_DP, gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_dp_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_SP_TOP, gen7_9_0_sp_pipe_br_cluster_sp_ps_sp_top_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_9_0_sp_pipe_br_cluster_sp_ps_usptp_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_HLSQ_DP_STR, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_HLSQ_DP_STR, gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_dp_str_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_HLSQ_DP, gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_dp_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_SP_TOP, gen7_9_0_sp_pipe_br_cluster_sp_ps_sp_top_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_USPTP, gen7_9_0_sp_pipe_br_cluster_sp_ps_usptp_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_HLSQ_DP_STR, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_HLSQ_DP_STR, gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_dp_str_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_HLSQ_DP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_HLSQ_DP, gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_dp_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_SP_TOP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_SP_TOP, gen7_9_0_sp_pipe_br_cluster_sp_ps_sp_top_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_USPTP, gen7_9_0_sp_pipe_br_cluster_sp_ps_usptp_registers, 0xa800}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_HLSQ_DP_STR, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_HLSQ_DP_STR, gen7_9_0_sp_pipe_br_cluster_sp_ps_hlsq_dp_str_registers, 0xa800}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_9_0_tpl1_pipe_br_cluster_sp_vs_usptp_registers, 0xb000}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, A7XX_PIPE_BV, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX0_3D_CVS_REG, PIPE_BV, 0, A7XX_USPTP, gen7_9_0_tpl1_pipe_bv_cluster_sp_vs_usptp_registers, 0xb000}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_9_0_tpl1_pipe_br_cluster_sp_vs_usptp_registers, 0xb000}, - { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, A7XX_PIPE_BV, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_VS, A7XX_SP_CTX1_3D_CVS_REG, PIPE_BV, 1, A7XX_USPTP, gen7_9_0_tpl1_pipe_bv_cluster_sp_vs_usptp_registers, 0xb000}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_BR, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_BR, 0, A7XX_USPTP, gen7_9_0_tpl1_pipe_br_cluster_sp_ps_usptp_registers, 0xb000}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, A7XX_PIPE_LPAC, 0, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX0_3D_CPS_REG, PIPE_LPAC, 0, A7XX_USPTP, gen7_9_0_tpl1_pipe_lpac_cluster_sp_ps_usptp_registers, 0xb000}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, A7XX_PIPE_BR, 1, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX1_3D_CPS_REG, PIPE_BR, 1, A7XX_USPTP, gen7_9_0_tpl1_pipe_br_cluster_sp_ps_usptp_registers, 0xb000}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, A7XX_PIPE_BR, 2, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX2_3D_CPS_REG, PIPE_BR, 2, A7XX_USPTP, gen7_9_0_tpl1_pipe_br_cluster_sp_ps_usptp_registers, 0xb000}, - { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, A7XX_PIPE_BR, 3, A7XX_USPTP, + { A7XX_CLUSTER_SP_PS, A7XX_SP_CTX3_3D_CPS_REG, PIPE_BR, 3, A7XX_USPTP, gen7_9_0_tpl1_pipe_br_cluster_sp_ps_usptp_registers, 0xb000}, }; -static struct a6xx_indexed_registers gen7_9_0_cp_indexed_reg_list[] = { +static const struct a6xx_indexed_registers gen7_9_0_cp_indexed_reg_list[] = { { "CP_SQE_STAT", REG_A6XX_CP_SQE_STAT_ADDR, REG_A6XX_CP_SQE_STAT_DATA, 0x00040}, { "CP_DRAW_STATE", REG_A6XX_CP_DRAW_STATE_ADDR, REG_A6XX_CP_DRAW_STATE_DATA, 0x00200}, - { "CP_ROQ", REG_A6XX_CP_ROQ_DBG_ADDR, + { "CP_ROQ_DBG", REG_A6XX_CP_ROQ_DBG_ADDR, REG_A6XX_CP_ROQ_DBG_DATA, 0x00800}, - { "CP_UCODE_DBG_DATA", REG_A6XX_CP_SQE_UCODE_DBG_ADDR, + { "CP_SQE_UCODE_DBG", REG_A6XX_CP_SQE_UCODE_DBG_ADDR, REG_A6XX_CP_SQE_UCODE_DBG_DATA, 0x08000}, - { "CP_BV_DRAW_STATE_ADDR", REG_A7XX_CP_BV_DRAW_STATE_ADDR, + { "CP_BV_DRAW_STATE", REG_A7XX_CP_BV_DRAW_STATE_ADDR, REG_A7XX_CP_BV_DRAW_STATE_DATA, 0x00200}, - { "CP_BV_ROQ_DBG_ADDR", REG_A7XX_CP_BV_ROQ_DBG_ADDR, + { "CP_BV_ROQ_DBG", REG_A7XX_CP_BV_ROQ_DBG_ADDR, REG_A7XX_CP_BV_ROQ_DBG_DATA, 0x00800}, - { "CP_BV_SQE_UCODE_DBG_ADDR", REG_A7XX_CP_BV_SQE_UCODE_DBG_ADDR, + { "CP_BV_SQE_UCODE_DBG", REG_A7XX_CP_BV_SQE_UCODE_DBG_ADDR, REG_A7XX_CP_BV_SQE_UCODE_DBG_DATA, 0x08000}, - { "CP_BV_SQE_STAT_ADDR", REG_A7XX_CP_BV_SQE_STAT_ADDR, + { "CP_BV_SQE_STAT", REG_A7XX_CP_BV_SQE_STAT_ADDR, REG_A7XX_CP_BV_SQE_STAT_DATA, 0x00040}, - { "CP_RESOURCE_TBL", REG_A7XX_CP_RESOURCE_TBL_DBG_ADDR, - REG_A7XX_CP_RESOURCE_TBL_DBG_DATA, 0x04100}, - { "CP_LPAC_DRAW_STATE_ADDR", REG_A7XX_CP_LPAC_DRAW_STATE_ADDR, + { "CP_RESOURCE_TABLE_DBG", REG_A7XX_CP_RESOURCE_TABLE_DBG_ADDR, + REG_A7XX_CP_RESOURCE_TABLE_DBG_DATA, 0x04100}, + { "CP_LPAC_DRAW_STATE", REG_A7XX_CP_LPAC_DRAW_STATE_ADDR, REG_A7XX_CP_LPAC_DRAW_STATE_DATA, 0x00200}, - { "CP_LPAC_ROQ", REG_A7XX_CP_LPAC_ROQ_DBG_ADDR, + { "CP_LPAC_ROQ_DBG", REG_A7XX_CP_LPAC_ROQ_DBG_ADDR, REG_A7XX_CP_LPAC_ROQ_DBG_DATA, 0x00200}, - { "CP_SQE_AC_UCODE_DBG_ADDR", REG_A7XX_CP_SQE_AC_UCODE_DBG_ADDR, + { "CP_SQE_AC_UCODE_DBG", REG_A7XX_CP_SQE_AC_UCODE_DBG_ADDR, REG_A7XX_CP_SQE_AC_UCODE_DBG_DATA, 0x08000}, - { "CP_SQE_AC_STAT_ADDR", REG_A7XX_CP_SQE_AC_STAT_ADDR, + { "CP_SQE_AC_STAT", REG_A7XX_CP_SQE_AC_STAT_ADDR, REG_A7XX_CP_SQE_AC_STAT_DATA, 0x00040}, - { "CP_LPAC_FIFO_DBG_ADDR", REG_A7XX_CP_LPAC_FIFO_DBG_ADDR, + { "CP_LPAC_FIFO_DBG", REG_A7XX_CP_LPAC_FIFO_DBG_ADDR, REG_A7XX_CP_LPAC_FIFO_DBG_DATA, 0x00040}, { "CP_AQE_ROQ_0", REG_A7XX_CP_AQE_ROQ_DBG_ADDR_0, REG_A7XX_CP_AQE_ROQ_DBG_DATA_0, 0x00100}, @@ -1337,7 +1337,7 @@ static struct a6xx_indexed_registers gen7_9_0_cp_indexed_reg_list[] = { REG_A7XX_CP_AQE_STAT_DATA_1, 0x00040}, }; -static struct gen7_reg_list gen7_9_0_reg_list[] = { +static const struct gen7_reg_list gen7_9_0_reg_list[] = { { gen7_9_0_gpu_registers, NULL}, { gen7_9_0_cx_misc_registers, NULL}, { gen7_9_0_cx_dbgc_registers, NULL}, diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 75f5367e73ca..1c80909e63ca 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -10,7 +10,7 @@ #include <linux/interconnect.h> #include <linux/firmware/qcom/qcom_scm.h> #include <linux/kernel.h> -#include <linux/of_address.h> +#include <linux/of_reserved_mem.h> #include <linux/pm_opp.h> #include <linux/slab.h> #include <linux/soc/qcom/mdt_loader.h> @@ -33,7 +33,7 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname, struct device *dev = &gpu->pdev->dev; const struct firmware *fw; const char *signed_fwname = NULL; - struct device_node *np, *mem_np; + struct device_node *np; struct resource r; phys_addr_t mem_phys; ssize_t mem_size; @@ -51,18 +51,11 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname, return -ENODEV; } - mem_np = of_parse_phandle(np, "memory-region", 0); - of_node_put(np); - if (!mem_np) { + ret = of_reserved_mem_region_to_resource(np, 0, &r); + if (ret) { zap_available = false; - return -EINVAL; - } - - ret = of_address_to_resource(mem_np, 0, &r); - of_node_put(mem_np); - if (ret) return ret; - + } mem_phys = r.start; /* @@ -191,25 +184,25 @@ int adreno_zap_shader_load(struct msm_gpu *gpu, u32 pasid) return zap_shader_load_mdt(gpu, adreno_gpu->info->zapfw, pasid); } -struct msm_gem_address_space * -adreno_create_address_space(struct msm_gpu *gpu, - struct platform_device *pdev) +struct drm_gpuvm * +adreno_create_vm(struct msm_gpu *gpu, + struct platform_device *pdev) { - return adreno_iommu_create_address_space(gpu, pdev, 0); + return adreno_iommu_create_vm(gpu, pdev, 0); } -struct msm_gem_address_space * -adreno_iommu_create_address_space(struct msm_gpu *gpu, - struct platform_device *pdev, - unsigned long quirks) +struct drm_gpuvm * +adreno_iommu_create_vm(struct msm_gpu *gpu, + struct platform_device *pdev, + unsigned long quirks) { struct iommu_domain_geometry *geometry; struct msm_mmu *mmu; - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; u64 start, size; mmu = msm_iommu_gpu_new(&pdev->dev, gpu, quirks); - if (IS_ERR_OR_NULL(mmu)) + if (IS_ERR(mmu)) return ERR_CAST(mmu); geometry = msm_iommu_get_geometry(mmu); @@ -224,47 +217,95 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu, start = max_t(u64, SZ_16M, geometry->aperture_start); size = geometry->aperture_end - start + 1; - aspace = msm_gem_address_space_create(mmu, "gpu", - start & GENMASK_ULL(48, 0), size); + vm = msm_gem_vm_create(gpu->dev, mmu, "gpu", start & GENMASK_ULL(48, 0), + size, true); - if (IS_ERR(aspace) && !IS_ERR(mmu)) + if (IS_ERR(vm) && !IS_ERR(mmu)) mmu->funcs->destroy(mmu); - return aspace; + return vm; } -u64 adreno_private_address_space_size(struct msm_gpu *gpu) +u64 adreno_private_vm_size(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(&gpu->pdev->dev); + const struct io_pgtable_cfg *ttbr1_cfg; if (address_space_size) return address_space_size; - if (adreno_gpu->info->address_space_size) - return adreno_gpu->info->address_space_size; + if (adreno_gpu->info->quirks & ADRENO_QUIRK_4GB_VA) + return SZ_4G; + + if (!adreno_smmu || !adreno_smmu->get_ttbr1_cfg) + return SZ_4G; + + ttbr1_cfg = adreno_smmu->get_ttbr1_cfg(adreno_smmu->cookie); - return SZ_4G; + /* + * Userspace VM is actually using TTBR0, but both are the same size, + * with b48 (sign bit) selecting which TTBRn to use. So if IAS is + * 48, the total (kernel+user) address space size is effectively + * 49 bits. But what userspace is control of is the lower 48. + */ + return BIT(ttbr1_cfg->ias) - ADRENO_VM_START; +} + +void adreno_check_and_reenable_stall(struct adreno_gpu *adreno_gpu) +{ + struct msm_gpu *gpu = &adreno_gpu->base; + struct msm_drm_private *priv = gpu->dev->dev_private; + unsigned long flags; + + /* + * Wait until the cooldown period has passed and we would actually + * collect a crashdump to re-enable stall-on-fault. + */ + spin_lock_irqsave(&priv->fault_stall_lock, flags); + if (!priv->stall_enabled && + ktime_after(ktime_get(), priv->stall_reenable_time) && + !READ_ONCE(gpu->crashstate)) { + struct msm_mmu *mmu = to_msm_vm(gpu->vm)->mmu; + + priv->stall_enabled = true; + + mmu->funcs->set_stall(mmu, true); + } + spin_unlock_irqrestore(&priv->fault_stall_lock, flags); } #define ARM_SMMU_FSR_TF BIT(1) #define ARM_SMMU_FSR_PF BIT(3) #define ARM_SMMU_FSR_EF BIT(4) +#define ARM_SMMU_FSR_SS BIT(30) int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags, struct adreno_smmu_fault_info *info, const char *block, u32 scratch[4]) { + struct adreno_gpu *adreno_gpu = container_of(gpu, struct adreno_gpu, base); + struct msm_drm_private *priv = gpu->dev->dev_private; + struct msm_mmu *mmu = to_msm_vm(gpu->vm)->mmu; const char *type = "UNKNOWN"; - bool do_devcoredump = info && !READ_ONCE(gpu->crashstate); + bool do_devcoredump = info && (info->fsr & ARM_SMMU_FSR_SS) && + !READ_ONCE(gpu->crashstate); + unsigned long irq_flags; /* - * If we aren't going to be resuming later from fault_worker, then do - * it now. + * In case there is a subsequent storm of pagefaults, disable + * stall-on-fault for at least half a second. */ - if (!do_devcoredump) { - gpu->aspace->mmu->funcs->resume_translation(gpu->aspace->mmu); + spin_lock_irqsave(&priv->fault_stall_lock, irq_flags); + if (priv->stall_enabled) { + priv->stall_enabled = false; + + mmu->funcs->set_stall(mmu, false); } + priv->stall_reenable_time = ktime_add_ms(ktime_get(), 500); + spin_unlock_irqrestore(&priv->fault_stall_lock, irq_flags); + /* * Print a default message if we couldn't get the data from the * adreno-smmu-priv @@ -291,29 +332,41 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags, scratch[0], scratch[1], scratch[2], scratch[3]); if (do_devcoredump) { + struct msm_gpu_fault_info fault_info = {}; + /* Turn off the hangcheck timer to keep it from bothering us */ - del_timer(&gpu->hangcheck_timer); + timer_delete(&gpu->hangcheck_timer); + + /* Let any concurrent GMU transactions know that the MMU may be + * blocked for a while and they should wait on us. + */ + reinit_completion(&adreno_gpu->fault_coredump_done); - gpu->fault_info.ttbr0 = info->ttbr0; - gpu->fault_info.iova = iova; - gpu->fault_info.flags = flags; - gpu->fault_info.type = type; - gpu->fault_info.block = block; + fault_info.ttbr0 = info->ttbr0; + fault_info.iova = iova; + fault_info.flags = flags; + fault_info.type = type; + fault_info.block = block; - kthread_queue_work(gpu->worker, &gpu->fault_work); + msm_gpu_fault_crashstate_capture(gpu, &fault_info); + + complete_all(&adreno_gpu->fault_coredump_done); } return 0; } -int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, +int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx, uint32_t param, uint64_t *value, uint32_t *len) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct drm_device *drm = gpu->dev; + /* Note ctx can be NULL when called from rd_open(): */ + struct drm_gpuvm *vm = ctx ? msm_context_vm(drm, ctx) : NULL; /* No pointer params yet */ if (*len != 0) - return -EINVAL; + return UERR(EINVAL, drm, "invalid len"); switch (param) { case MSM_PARAM_GPU_ID: @@ -355,8 +408,8 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, *value = 0; return 0; case MSM_PARAM_FAULTS: - if (ctx->aspace) - *value = gpu->global_faults + ctx->aspace->faults; + if (vm) + *value = gpu->global_faults + to_msm_vm(vm)->faults; else *value = gpu->global_faults; return 0; @@ -364,36 +417,43 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, *value = gpu->suspend_count; return 0; case MSM_PARAM_VA_START: - if (ctx->aspace == gpu->aspace) - return -EINVAL; - *value = ctx->aspace->va_start; + if (vm == gpu->vm) + return UERR(EINVAL, drm, "requires per-process pgtables"); + *value = vm->mm_start; return 0; case MSM_PARAM_VA_SIZE: - if (ctx->aspace == gpu->aspace) - return -EINVAL; - *value = ctx->aspace->va_size; + if (vm == gpu->vm) + return UERR(EINVAL, drm, "requires per-process pgtables"); + *value = vm->mm_range; return 0; case MSM_PARAM_HIGHEST_BANK_BIT: - *value = adreno_gpu->ubwc_config.highest_bank_bit; + *value = adreno_gpu->ubwc_config->highest_bank_bit; return 0; case MSM_PARAM_RAYTRACING: *value = adreno_gpu->has_ray_tracing; return 0; case MSM_PARAM_UBWC_SWIZZLE: - *value = adreno_gpu->ubwc_config.ubwc_swizzle; + *value = adreno_gpu->ubwc_config->ubwc_swizzle; return 0; case MSM_PARAM_MACROTILE_MODE: - *value = adreno_gpu->ubwc_config.macrotile_mode; + *value = adreno_gpu->ubwc_config->macrotile_mode; + return 0; + case MSM_PARAM_UCHE_TRAP_BASE: + *value = adreno_gpu->uche_trap_base; + return 0; + case MSM_PARAM_HAS_PRR: + *value = adreno_smmu_has_prr(gpu); return 0; default: - DBG("%s: invalid param: %u", gpu->name, param); - return -EINVAL; + return UERR(EINVAL, drm, "%s: invalid param: %u", gpu->name, param); } } -int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx, +int adreno_set_param(struct msm_gpu *gpu, struct msm_context *ctx, uint32_t param, uint64_t value, uint32_t len) { + struct drm_device *drm = gpu->dev; + switch (param) { case MSM_PARAM_COMM: case MSM_PARAM_CMDLINE: @@ -401,11 +461,11 @@ int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx, * that should be a reasonable upper bound */ if (len > PAGE_SIZE) - return -EINVAL; + return UERR(EINVAL, drm, "invalid len"); break; default: if (len != 0) - return -EINVAL; + return UERR(EINVAL, drm, "invalid len"); } switch (param) { @@ -434,11 +494,25 @@ int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx, } case MSM_PARAM_SYSPROF: if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - return msm_file_private_set_sysprof(ctx, gpu, value); + return UERR(EPERM, drm, "invalid permissions"); + return msm_context_set_sysprof(ctx, gpu, value); + case MSM_PARAM_EN_VM_BIND: + /* We can only support VM_BIND with per-process pgtables: */ + if (ctx->vm == gpu->vm) + return UERR(EINVAL, drm, "requires per-process pgtables"); + + /* + * We can only swtich to VM_BIND mode if the VM has not yet + * been created: + */ + if (ctx->vm) + return UERR(EBUSY, drm, "VM already created"); + + ctx->userspace_managed_vm = value; + + return 0; default: - DBG("%s: invalid param: %u", gpu->name, param); - return -EINVAL; + return UERR(EINVAL, drm, "%s: invalid param: %u", gpu->name, param); } } @@ -558,7 +632,7 @@ struct drm_gem_object *adreno_fw_create_bo(struct msm_gpu *gpu, void *ptr; ptr = msm_gem_kernel_new(gpu->dev, fw->size - 4, - MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->aspace, &bo, iova); + MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->vm, &bo, iova); if (IS_ERR(ptr)) return ERR_CAST(ptr); @@ -751,6 +825,7 @@ void adreno_gpu_state_destroy(struct msm_gpu_state *state) for (i = 0; state->bos && i < state->nr_bos; i++) kvfree(state->bos[i].data); + kfree(state->vm_logs); kfree(state->bos); kfree(state->comm); kfree(state->cmd); @@ -879,6 +954,26 @@ void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state, drm_printf(p, " - dir=%s\n", info->flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ"); drm_printf(p, " - type=%s\n", info->type); drm_printf(p, " - source=%s\n", info->block); + + /* Information extracted from what we think are the current + * pgtables. Hopefully the TTBR0 matches what we've extracted + * from the SMMU registers in smmu_info! + */ + drm_puts(p, "pgtable-fault-info:\n"); + drm_printf(p, " - ttbr0: %.16llx\n", (u64)info->pgtbl_ttbr0); + drm_printf(p, " - asid: %d\n", info->asid); + drm_printf(p, " - ptes: %.16llx %.16llx %.16llx %.16llx\n", + info->ptes[0], info->ptes[1], info->ptes[2], info->ptes[3]); + } + + if (state->vm_logs) { + drm_puts(p, "vm-log:\n"); + for (i = 0; i < state->nr_vm_logs; i++) { + struct msm_gem_vm_log_entry *e = &state->vm_logs[i]; + drm_printf(p, " - %s:%d: 0x%016llx-0x%016llx\n", + e->op, e->queue_id, e->iova, + e->iova + e->range); + } } drm_printf(p, "rbbm-status: 0x%08x\n", state->rbbm_status); @@ -1102,6 +1197,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, /* Only handle the core clock when GMU is not in use (or is absent). */ if (adreno_has_gmu_wrapper(adreno_gpu) || + adreno_has_rgmu(adreno_gpu) || adreno_gpu->info->family < ADRENO_6XX_GEN1) { /* * This can only be done before devm_pm_opp_of_add_table(), or @@ -1135,6 +1231,9 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, if (ret) return ret; + init_completion(&adreno_gpu->fault_coredump_done); + complete_all(&adreno_gpu->fault_coredump_done); + pm_runtime_set_autosuspend_delay(dev, adreno_gpu->info->inactive_period); pm_runtime_use_autosuspend(dev); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index e71f420f8b3a..0f8d3de97636 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -12,13 +12,14 @@ #include <linux/firmware.h> #include <linux/iopoll.h> +#include <linux/soc/qcom/ubwc.h> + #include "msm_gpu.h" #include "adreno_common.xml.h" #include "adreno_pm4.xml.h" extern bool snapshot_debugbus; -extern bool allow_vram_carveout; enum { ADRENO_FW_PM4 = 0, @@ -26,6 +27,7 @@ enum { ADRENO_FW_PFP = 1, ADRENO_FW_GMU = 1, /* a6xx */ ADRENO_FW_GPMU = 2, + ADRENO_FW_AQE = 3, ADRENO_FW_MAX, }; @@ -49,6 +51,8 @@ enum adreno_family { ADRENO_7XX_GEN1, /* a730 family */ ADRENO_7XX_GEN2, /* a740 family */ ADRENO_7XX_GEN3, /* a750 family */ + ADRENO_8XX_GEN1, /* a830 family */ + ADRENO_8XX_GEN2, /* a840 family */ }; #define ADRENO_QUIRK_TWO_PASS_USE_WFI BIT(0) @@ -57,6 +61,8 @@ enum adreno_family { #define ADRENO_QUIRK_HAS_HW_APRIV BIT(3) #define ADRENO_QUIRK_HAS_CACHED_COHERENT BIT(4) #define ADRENO_QUIRK_PREEMPTION BIT(5) +#define ADRENO_QUIRK_4GB_VA BIT(6) +#define ADRENO_QUIRK_IFPC BIT(7) /* Helper for formating the chip_id in the way that userspace tools like * crashdec expect. @@ -68,9 +74,14 @@ enum adreno_family { (((_c) >> 8) & 0xff), \ ((_c) & 0xff) +struct adreno_gpu; + struct adreno_gpu_funcs { struct msm_gpu_funcs base; + struct msm_gpu *(*init)(struct drm_device *dev); int (*get_timestamp)(struct msm_gpu *gpu, uint64_t *value); + void (*bus_halt)(struct adreno_gpu *adreno_gpu, bool gx_off); + int (*mmu_fault_handler)(void *arg, unsigned long iova, int flags, void *data); }; struct adreno_reglist { @@ -78,6 +89,13 @@ struct adreno_reglist { u32 value; }; +/* Reglist with pipe information */ +struct adreno_reglist_pipe { + u32 offset; + u32 value; + u32 pipe; +}; + struct adreno_speedbin { uint16_t fuse; uint16_t speedbin; @@ -98,13 +116,12 @@ struct adreno_info { const char *fw[ADRENO_FW_MAX]; uint32_t gmem; u64 quirks; - struct msm_gpu *(*init)(struct drm_device *dev); + const struct adreno_gpu_funcs *funcs; const char *zapfw; u32 inactive_period; union { const struct a6xx_info *a6xx; }; - u64 address_space_size; /** * @speedbins: Optional table of fuse to speedbin mappings * @@ -178,6 +195,8 @@ struct adreno_gpu { uint16_t speedbin; const struct adreno_gpu_funcs *funcs; + struct completion fault_coredump_done; + /* interesting register offsets to dump: */ const unsigned int *registers; @@ -205,44 +224,12 @@ struct adreno_gpu { /* firmware: */ const struct firmware *fw[ADRENO_FW_MAX]; - struct { - /** - * @rgb565_predicator: Unknown, introduced with A650 family, - * related to UBWC mode/ver 4 - */ - u32 rgb565_predicator; - /** @uavflagprd_inv: Unknown, introduced with A650 family */ - u32 uavflagprd_inv; - /** @min_acc_len: Whether the minimum access length is 64 bits */ - u32 min_acc_len; - /** - * @ubwc_swizzle: Whether to enable level 1, 2 & 3 bank swizzling. - * - * UBWC 1.0 always enables all three levels. - * UBWC 2.0 removes level 1 bank swizzling, leaving levels 2 & 3. - * UBWC 4.0 adds the optional ability to disable levels 2 & 3. - * - * This is a bitmask where BIT(0) enables level 1, BIT(1) - * controls level 2, and BIT(2) enables level 3. - */ - u32 ubwc_swizzle; - /** - * @highest_bank_bit: Highest Bank Bit - * - * The Highest Bank Bit value represents the bit of the highest - * DDR bank. This should ideally use DRAM type detection. - */ - u32 highest_bank_bit; - u32 amsbc; - /** - * @macrotile_mode: Macrotile Mode - * - * Whether to use 4-channel macrotiling mode or the newer - * 8-channel macrotiling mode introduced in UBWC 3.1. 0 is - * 4-channel and 1 is 8-channel. - */ - u32 macrotile_mode; - } ubwc_config; + /* + * The migration to the central UBWC config db is still in flight - keep + * a copy containing some local fixups until that's done. + */ + const struct qcom_ubwc_cfg_data *ubwc_config; + struct qcom_ubwc_cfg_data _ubwc_config; /* * Register offsets are different between some GPUs. @@ -253,6 +240,8 @@ struct adreno_gpu { bool gmu_is_wrapper; bool has_ray_tracing; + + u64 uche_trap_base; }; #define to_adreno_gpu(x) container_of(x, struct adreno_gpu, base) @@ -420,6 +409,16 @@ static inline int adreno_is_a610(const struct adreno_gpu *gpu) return adreno_is_revn(gpu, 610); } +static inline int adreno_is_a612(const struct adreno_gpu *gpu) +{ + return gpu->info->chip_ids[0] == 0x06010200; +} + +static inline bool adreno_has_rgmu(const struct adreno_gpu *gpu) +{ + return adreno_is_a612(gpu); +} + static inline int adreno_is_a618(const struct adreno_gpu *gpu) { return adreno_is_revn(gpu, 618); @@ -440,6 +439,11 @@ static inline int adreno_is_a621(const struct adreno_gpu *gpu) return gpu->info->chip_ids[0] == 0x06020100; } +static inline int adreno_is_a623(const struct adreno_gpu *gpu) +{ + return gpu->info->chip_ids[0] == 0x06020300; +} + static inline int adreno_is_a630(const struct adreno_gpu *gpu) { return adreno_is_revn(gpu, 630); @@ -489,9 +493,9 @@ static inline int adreno_is_a610_family(const struct adreno_gpu *gpu) { if (WARN_ON_ONCE(!gpu->info)) return false; - - /* TODO: A612 */ - return adreno_is_a610(gpu) || adreno_is_a702(gpu); + return adreno_is_a610(gpu) || + adreno_is_a612(gpu) || + adreno_is_a702(gpu); } /* TODO: 615/616 */ @@ -559,6 +563,11 @@ static inline int adreno_is_a740_family(struct adreno_gpu *gpu) gpu->info->family == ADRENO_7XX_GEN3; } +static inline int adreno_is_a750_family(struct adreno_gpu *gpu) +{ + return gpu->info->family == ADRENO_7XX_GEN3; +} + static inline int adreno_is_a7xx(struct adreno_gpu *gpu) { /* Update with non-fake (i.e. non-A702) Gen 7 GPUs */ @@ -566,10 +575,27 @@ static inline int adreno_is_a7xx(struct adreno_gpu *gpu) 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, +static inline int adreno_is_a8xx(struct adreno_gpu *gpu) +{ + return gpu->info->family >= ADRENO_8XX_GEN1; +} + +static inline int adreno_is_x285(struct adreno_gpu *gpu) +{ + return gpu->info->chip_ids[0] == 0x44070001; +} + +static inline int adreno_is_a840(struct adreno_gpu *gpu) +{ + return gpu->info->chip_ids[0] == 0x44050a01; +} + +/* Put vm_start above 32b to catch issues with not setting xyz_BASE_HI */ +#define ADRENO_VM_START 0x100000000ULL +u64 adreno_private_vm_size(struct msm_gpu *gpu); +int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx, uint32_t param, uint64_t *value, uint32_t *len); -int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx, +int adreno_set_param(struct msm_gpu *gpu, struct msm_context *ctx, uint32_t param, uint64_t value, uint32_t len); const struct firmware *adreno_request_fw(struct adreno_gpu *adreno_gpu, const char *fwname); @@ -609,19 +635,21 @@ void adreno_show_object(struct drm_printer *p, void **ptr, int len, * Common helper function to initialize the default address space for arm-smmu * attached targets */ -struct msm_gem_address_space * -adreno_create_address_space(struct msm_gpu *gpu, - struct platform_device *pdev); +struct drm_gpuvm * +adreno_create_vm(struct msm_gpu *gpu, + struct platform_device *pdev); -struct msm_gem_address_space * -adreno_iommu_create_address_space(struct msm_gpu *gpu, - struct platform_device *pdev, - unsigned long quirks); +struct drm_gpuvm * +adreno_iommu_create_vm(struct msm_gpu *gpu, + struct platform_device *pdev, + unsigned long quirks); int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags, struct adreno_smmu_fault_info *info, const char *block, u32 scratch[4]); +void adreno_check_and_reenable_stall(struct adreno_gpu *gpu); + int adreno_read_speedbin(struct device *dev, u32 *speedbin); /* @@ -687,12 +715,6 @@ OUT_PKT7(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt) OUT_RING(ring, PKT7(opcode, cnt)); } -struct msm_gpu *a2xx_gpu_init(struct drm_device *dev); -struct msm_gpu *a3xx_gpu_init(struct drm_device *dev); -struct msm_gpu *a4xx_gpu_init(struct drm_device *dev); -struct msm_gpu *a5xx_gpu_init(struct drm_device *dev); -struct msm_gpu *a6xx_gpu_init(struct drm_device *dev); - static inline uint32_t get_wptr(struct msm_ringbuffer *ring) { return (ring->cur - ring->start) % (MSM_GPU_RINGBUFFER_SZ >> 2); diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h index eb5dfff2ec4f..56d3c38c8778 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h @@ -21,43 +21,35 @@ static const struct dpu_caps sm8650_dpu_caps = { static const struct dpu_mdp_cfg sm8650_mdp = { .name = "top_0", .base = 0, .len = 0x494, - .features = BIT(DPU_MDP_PERIPH_0_REMOVED), .clk_ctrls = { [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8650_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x1000, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x1000, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x17000, .len = 0x1000, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x18000, .len = 0x1000, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x19000, .len = 0x1000, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a000, .len = 0x1000, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -140,7 +132,7 @@ static const struct dpu_lm_cfg sm8650_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -148,7 +140,7 @@ static const struct dpu_lm_cfg sm8650_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -156,28 +148,30 @@ static const struct dpu_lm_cfg sm8650_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, + .dspp = DSPP_2, }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, + .dspp = DSPP_3, }, { .name = "lm_4", .id = LM_4, .base = 0x48000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_5, .pingpong = PINGPONG_4, }, { .name = "lm_5", .id = LM_5, .base = 0x49000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_4, .pingpong = PINGPONG_5, @@ -188,22 +182,18 @@ static const struct dpu_dspp_cfg sm8650_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_2", .id = DSPP_2, .base = 0x58000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_3", .id = DSPP_3, .base = 0x5a000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -212,67 +202,57 @@ static const struct dpu_pingpong_cfg sm8650_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x69000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x6d000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x6e000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), }, { - .name = "pingpong_6", .id = PINGPONG_6, + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, .base = 0x66000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, }, { - .name = "pingpong_7", .id = PINGPONG_7, + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, .base = 0x66400, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, }, { - .name = "pingpong_8", .id = PINGPONG_8, + .name = "pingpong_cwb_2", .id = PINGPONG_CWB_2, .base = 0x7e000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_4, }, { - .name = "pingpong_9", .id = PINGPONG_9, + .name = "pingpong_cwb_3", .id = PINGPONG_CWB_3, .base = 0x7e400, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_4, }, @@ -306,32 +286,30 @@ static const struct dpu_dsc_cfg sm8650_dsc[] = { { .name = "dce_0_0", .id = DSC_0, .base = 0x80000, .len = 0x6, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_0, }, { .name = "dce_0_1", .id = DSC_1, .base = 0x80000, .len = 0x6, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_1, }, { .name = "dce_1_0", .id = DSC_2, .base = 0x81000, .len = 0x6, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_0, }, { .name = "dce_1_1", .id = DSC_3, .base = 0x81000, .len = 0x6, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_1, }, { .name = "dce_2_0", .id = DSC_4, .base = 0x82000, .len = 0x6, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_0, }, { .name = "dce_2_1", .id = DSC_5, .base = 0x82000, .len = 0x6, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_1, }, }; @@ -340,9 +318,9 @@ static const struct dpu_wb_cfg sm8650_wb[] = { { .name = "wb_2", .id = WB_2, .base = 0x65000, .len = 0x2c8, - .features = WB_SM8250_MASK, - .format_list = wb2_formats_rgb, - .num_formats = ARRAY_SIZE(wb2_formats_rgb), + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .xin_id = 6, .vbif_idx = VBIF_RT, .maxlinewidth = 4096, @@ -350,11 +328,29 @@ static const struct dpu_wb_cfg sm8650_wb[] = { }, }; +static const struct dpu_cwb_cfg sm8650_cwb[] = { + { + .name = "cwb_0", .id = CWB_0, + .base = 0x66200, .len = 0x8, + }, + { + .name = "cwb_1", .id = CWB_1, + .base = 0x66600, .len = 0x8, + }, + { + .name = "cwb_2", .id = CWB_2, + .base = 0x7E200, .len = 0x8, + }, + { + .name = "cwb_3", .id = CWB_3, + .base = 0x7E600, .len = 0x8, + }, +}; + static const struct dpu_intf_cfg sm8650_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x34000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -363,7 +359,6 @@ static const struct dpu_intf_cfg sm8650_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -373,7 +368,6 @@ static const struct dpu_intf_cfg sm8650_intf[] = { }, { .name = "intf_2", .id = INTF_2, .base = 0x36000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -383,7 +377,6 @@ static const struct dpu_intf_cfg sm8650_intf[] = { }, { .name = "intf_3", .id = INTF_3, .base = 0x37000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -431,6 +424,7 @@ const struct dpu_mdss_cfg dpu_sm8650_cfg = { .mdss_ver = &sm8650_mdss_ver, .caps = &sm8650_dpu_caps, .mdp = &sm8650_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sm8650_ctl), .ctl = sm8650_ctl, .sspp_count = ARRAY_SIZE(sm8650_sspp), @@ -447,6 +441,8 @@ const struct dpu_mdss_cfg dpu_sm8650_cfg = { .merge_3d = sm8650_merge_3d, .wb_count = ARRAY_SIZE(sm8650_wb), .wb = sm8650_wb, + .cwb_count = ARRAY_SIZE(sm8650_cwb), + .cwb = sm8650_cwb, .intf_count = ARRAY_SIZE(sm8650_intf), .intf = sm8650_intf, .vbif_count = ARRAY_SIZE(sm8650_vbif), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h new file mode 100644 index 000000000000..db8cc2d0112c --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h @@ -0,0 +1,494 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025 Linaro Limited + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. + */ + +#ifndef _DPU_12_0_SM8750_H +#define _DPU_12_0_SM8750_H + +static const struct dpu_caps sm8750_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0xb, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 8192, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, +}; + +static const struct dpu_mdp_cfg sm8750_mdp = { + .name = "top_0", + .base = 0, .len = 0x494, + .clk_ctrls = { + [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, + }, +}; + +static const struct dpu_ctl_cfg sm8750_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x15000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, { + .name = "ctl_1", .id = CTL_1, + .base = 0x16000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, { + .name = "ctl_2", .id = CTL_2, + .base = 0x17000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, { + .name = "ctl_3", .id = CTL_3, + .base = 0x18000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, { + .name = "ctl_4", .id = CTL_4, + .base = 0x19000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, { + .name = "ctl_5", .id = CTL_5, + .base = 0x1a000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), + }, +}; + +static const struct dpu_sspp_cfg sm8750_sspp[] = { + { + .name = "sspp_0", .id = SSPP_VIG0, + .base = 0x4000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 0, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_1", .id = SSPP_VIG1, + .base = 0x6000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 4, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_2", .id = SSPP_VIG2, + .base = 0x8000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 8, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_3", .id = SSPP_VIG3, + .base = 0xa000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 12, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_8", .id = SSPP_DMA0, + .base = 0x24000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 1, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_9", .id = SSPP_DMA1, + .base = 0x26000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 5, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_10", .id = SSPP_DMA2, + .base = 0x28000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 9, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_11", .id = SSPP_DMA3, + .base = 0x2a000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 13, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_12", .id = SSPP_DMA4, + .base = 0x2c000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 14, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_13", .id = SSPP_DMA5, + .base = 0x2e000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 15, + .type = SSPP_TYPE_DMA, + }, +}; + +static const struct dpu_lm_cfg sm8750_lm[] = { + { + .name = "lm_0", .id = LM_0, + .base = 0x44000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_1, + .pingpong = PINGPONG_0, + .dspp = DSPP_0, + }, { + .name = "lm_1", .id = LM_1, + .base = 0x45000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_0, + .pingpong = PINGPONG_1, + .dspp = DSPP_1, + }, { + .name = "lm_2", .id = LM_2, + .base = 0x46000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_3, + .pingpong = PINGPONG_2, + .dspp = DSPP_2, + }, { + .name = "lm_3", .id = LM_3, + .base = 0x47000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_2, + .pingpong = PINGPONG_3, + .dspp = DSPP_3, + }, { + .name = "lm_4", .id = LM_4, + .base = 0x48000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_5, + .pingpong = PINGPONG_4, + }, { + .name = "lm_5", .id = LM_5, + .base = 0x49000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_4, + .pingpong = PINGPONG_5, + }, { + .name = "lm_6", .id = LM_6, + .base = 0x4a000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_7, + .pingpong = PINGPONG_6, + }, { + .name = "lm_7", .id = LM_7, + .base = 0x4b000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_6, + .pingpong = PINGPONG_7, + }, +}; + +static const struct dpu_dspp_cfg sm8750_dspp[] = { + { + .name = "dspp_0", .id = DSPP_0, + .base = 0x54000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_1", .id = DSPP_1, + .base = 0x56000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_2", .id = DSPP_2, + .base = 0x58000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_3", .id = DSPP_3, + .base = 0x5a000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, +}; + +static const struct dpu_pingpong_cfg sm8750_pp[] = { + { + .name = "pingpong_0", .id = PINGPONG_0, + .base = 0x69000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + }, { + .name = "pingpong_1", .id = PINGPONG_1, + .base = 0x6a000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), + }, { + .name = "pingpong_2", .id = PINGPONG_2, + .base = 0x6b000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + }, { + .name = "pingpong_3", .id = PINGPONG_3, + .base = 0x6c000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), + }, { + .name = "pingpong_4", .id = PINGPONG_4, + .base = 0x6d000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), + }, { + .name = "pingpong_5", .id = PINGPONG_5, + .base = 0x6e000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), + }, { + .name = "pingpong_6", .id = PINGPONG_6, + .base = 0x6f000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 20), + }, { + .name = "pingpong_7", .id = PINGPONG_7, + .base = 0x70000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 21), + }, { + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, + .base = 0x66000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_4, + }, { + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, + .base = 0x66400, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_4, + }, { + .name = "pingpong_cwb_2", .id = PINGPONG_CWB_2, + .base = 0x7e000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_5, + }, { + .name = "pingpong_cwb_3", .id = PINGPONG_CWB_3, + .base = 0x7e400, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_5, + }, +}; + +static const struct dpu_merge_3d_cfg sm8750_merge_3d[] = { + { + .name = "merge_3d_0", .id = MERGE_3D_0, + .base = 0x4e000, .len = 0x1c, + }, { + .name = "merge_3d_1", .id = MERGE_3D_1, + .base = 0x4f000, .len = 0x1c, + }, { + .name = "merge_3d_2", .id = MERGE_3D_2, + .base = 0x50000, .len = 0x1c, + }, { + .name = "merge_3d_3", .id = MERGE_3D_3, + .base = 0x51000, .len = 0x1c, + }, { + .name = "merge_3d_4", .id = MERGE_3D_4, + .base = 0x66700, .len = 0x1c, + }, { + .name = "merge_3d_5", .id = MERGE_3D_5, + .base = 0x7e700, .len = 0x1c, + }, +}; + +/* + * NOTE: Each display compression engine (DCE) contains dual hard + * slice DSC encoders so both share same base address but with + * its own different sub block address. + */ +static const struct dpu_dsc_cfg sm8750_dsc[] = { + { + .name = "dce_0_0", .id = DSC_0, + .base = 0x80000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_0_1", .id = DSC_1, + .base = 0x80000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_1_0", .id = DSC_2, + .base = 0x81000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_1_1", .id = DSC_3, + .base = 0x81000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_2_0", .id = DSC_4, + .base = 0x82000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_2_1", .id = DSC_5, + .base = 0x82000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_3_0", .id = DSC_6, + .base = 0x83000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_3_1", .id = DSC_7, + .base = 0x83000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, +}; + +static const struct dpu_wb_cfg sm8750_wb[] = { + { + .name = "wb_2", .id = WB_2, + .base = 0x65000, .len = 0x2c8, + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), + .xin_id = 6, + .vbif_idx = VBIF_RT, + .maxlinewidth = 4096, + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), + }, +}; + +static const struct dpu_cwb_cfg sm8750_cwb[] = { + { + .name = "cwb_0", .id = CWB_0, + .base = 0x66200, .len = 0x20, + }, + { + .name = "cwb_1", .id = CWB_1, + .base = 0x66600, .len = 0x20, + }, + { + .name = "cwb_2", .id = CWB_2, + .base = 0x7e200, .len = 0x20, + }, + { + .name = "cwb_3", .id = CWB_3, + .base = 0x7e600, .len = 0x20, + }, +}; + +static const struct dpu_intf_cfg sm8750_intf[] = { + { + .name = "intf_0", .id = INTF_0, + .base = 0x34000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .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), + }, { + .name = "intf_1", .id = INTF_1, + .base = 0x35000, .len = 0x4bc, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_0, + .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 = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2), + }, { + .name = "intf_2", .id = INTF_2, + .base = 0x36000, .len = 0x4bc, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_1, + .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 = DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2), + }, { + .name = "intf_3", .id = INTF_3, + .base = 0x37000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, + .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), + }, +}; + +static const struct dpu_perf_cfg sm8750_perf_data = { + .max_bw_low = 18900000, + .max_bw_high = 28500000, + .min_core_ib = 2500000, + .min_llcc_ib = 0, + .min_dram_ib = 800000, + .min_prefill_lines = 35, + .danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0}, + .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(sc7180_qos_linear), + .entries = sc7180_qos_linear + }, + {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), + .entries = sc7180_qos_macrotile + }, + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), + .entries = sc7180_qos_nrt + }, + /* TODO: macrotile-qseed is different from macrotile */ + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; + +static const struct dpu_mdss_version sm8750_mdss_ver = { + .core_major_ver = 12, + .core_minor_ver = 0, +}; + +const struct dpu_mdss_cfg dpu_sm8750_cfg = { + .mdss_ver = &sm8750_mdss_ver, + .caps = &sm8750_dpu_caps, + .mdp = &sm8750_mdp, + .cdm = &dpu_cdm_5_x, + .ctl_count = ARRAY_SIZE(sm8750_ctl), + .ctl = sm8750_ctl, + .sspp_count = ARRAY_SIZE(sm8750_sspp), + .sspp = sm8750_sspp, + .mixer_count = ARRAY_SIZE(sm8750_lm), + .mixer = sm8750_lm, + .dspp_count = ARRAY_SIZE(sm8750_dspp), + .dspp = sm8750_dspp, + .pingpong_count = ARRAY_SIZE(sm8750_pp), + .pingpong = sm8750_pp, + .dsc_count = ARRAY_SIZE(sm8750_dsc), + .dsc = sm8750_dsc, + .merge_3d_count = ARRAY_SIZE(sm8750_merge_3d), + .merge_3d = sm8750_merge_3d, + .wb_count = ARRAY_SIZE(sm8750_wb), + .wb = sm8750_wb, + .cwb_count = ARRAY_SIZE(sm8750_cwb), + .cwb = sm8650_cwb, + .intf_count = ARRAY_SIZE(sm8750_intf), + .intf = sm8750_intf, + .vbif_count = ARRAY_SIZE(sm8650_vbif), + .vbif = sm8650_vbif, + .perf = &sm8750_perf_data, +}; + +#endif diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h new file mode 100644 index 000000000000..13bb43ba67d3 --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h @@ -0,0 +1,541 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025 Linaro Limited + */ + +#ifndef _DPU_12_2_GLYMUR_H +#define _DPU_12_2_GLYMUR_H + +static const struct dpu_caps glymur_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0xb, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 8192, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, +}; + +static const struct dpu_mdp_cfg glymur_mdp = { + .name = "top_0", + .base = 0, .len = 0x494, + .clk_ctrls = { + [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, + }, +}; + +static const struct dpu_ctl_cfg glymur_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x15000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, { + .name = "ctl_1", .id = CTL_1, + .base = 0x16000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, { + .name = "ctl_2", .id = CTL_2, + .base = 0x17000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, { + .name = "ctl_3", .id = CTL_3, + .base = 0x18000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, { + .name = "ctl_4", .id = CTL_4, + .base = 0x19000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, { + .name = "ctl_5", .id = CTL_5, + .base = 0x1a000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), + }, { + .name = "ctl_6", .id = CTL_6, + .base = 0x1b000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 14), + }, { + .name = "ctl_7", .id = CTL_7, + .base = 0x1c000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 15), + }, +}; + +static const struct dpu_sspp_cfg glymur_sspp[] = { + { + .name = "sspp_0", .id = SSPP_VIG0, + .base = 0x4000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 0, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_1", .id = SSPP_VIG1, + .base = 0x6000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 4, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_2", .id = SSPP_VIG2, + .base = 0x8000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 8, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_3", .id = SSPP_VIG3, + .base = 0xa000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 12, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_8", .id = SSPP_DMA0, + .base = 0x24000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 1, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_9", .id = SSPP_DMA1, + .base = 0x26000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 5, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_10", .id = SSPP_DMA2, + .base = 0x28000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 9, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_11", .id = SSPP_DMA3, + .base = 0x2a000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 13, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_12", .id = SSPP_DMA4, + .base = 0x2c000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 14, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_13", .id = SSPP_DMA5, + .base = 0x2e000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 15, + .type = SSPP_TYPE_DMA, + }, +}; + +static const struct dpu_lm_cfg glymur_lm[] = { + { + .name = "lm_0", .id = LM_0, + .base = 0x44000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_1, + .pingpong = PINGPONG_0, + .dspp = DSPP_0, + }, { + .name = "lm_1", .id = LM_1, + .base = 0x45000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_0, + .pingpong = PINGPONG_1, + .dspp = DSPP_1, + }, { + .name = "lm_2", .id = LM_2, + .base = 0x46000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_3, + .pingpong = PINGPONG_2, + .dspp = DSPP_2, + }, { + .name = "lm_3", .id = LM_3, + .base = 0x47000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_2, + .pingpong = PINGPONG_3, + .dspp = DSPP_3, + }, { + .name = "lm_4", .id = LM_4, + .base = 0x48000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_5, + .pingpong = PINGPONG_4, + }, { + .name = "lm_5", .id = LM_5, + .base = 0x49000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_4, + .pingpong = PINGPONG_5, + }, { + .name = "lm_6", .id = LM_6, + .base = 0x4a000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_7, + .pingpong = PINGPONG_6, + }, { + .name = "lm_7", .id = LM_7, + .base = 0x4b000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_6, + .pingpong = PINGPONG_7, + }, +}; + +static const struct dpu_dspp_cfg glymur_dspp[] = { + { + .name = "dspp_0", .id = DSPP_0, + .base = 0x54000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_1", .id = DSPP_1, + .base = 0x56000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_2", .id = DSPP_2, + .base = 0x58000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_3", .id = DSPP_3, + .base = 0x5a000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_4", .id = DSPP_4, + .base = 0x5c000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_5", .id = DSPP_5, + .base = 0x5e000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_6", .id = DSPP_6, + .base = 0x60000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_7", .id = DSPP_7, + .base = 0x62000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, +}; + +static const struct dpu_pingpong_cfg glymur_pp[] = { + { + .name = "pingpong_0", .id = PINGPONG_0, + .base = 0x69000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + }, { + .name = "pingpong_1", .id = PINGPONG_1, + .base = 0x6a000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), + }, { + .name = "pingpong_2", .id = PINGPONG_2, + .base = 0x6b000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + }, { + .name = "pingpong_3", .id = PINGPONG_3, + .base = 0x6c000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), + }, { + .name = "pingpong_4", .id = PINGPONG_4, + .base = 0x6d000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), + }, { + .name = "pingpong_5", .id = PINGPONG_5, + .base = 0x6e000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), + }, { + .name = "pingpong_6", .id = PINGPONG_6, + .base = 0x6f000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 20), + }, { + .name = "pingpong_7", .id = PINGPONG_7, + .base = 0x70000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 21), + }, { + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, + .base = 0x66000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_4, + }, { + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, + .base = 0x66400, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_4, + }, +}; + +static const struct dpu_merge_3d_cfg glymur_merge_3d[] = { + { + .name = "merge_3d_0", .id = MERGE_3D_0, + .base = 0x4e000, .len = 0x1c, + }, { + .name = "merge_3d_1", .id = MERGE_3D_1, + .base = 0x4f000, .len = 0x1c, + }, { + .name = "merge_3d_2", .id = MERGE_3D_2, + .base = 0x50000, .len = 0x1c, + }, { + .name = "merge_3d_3", .id = MERGE_3D_3, + .base = 0x51000, .len = 0x1c, + }, +}; + +/* + * NOTE: Each display compression engine (DCE) contains dual hard + * slice DSC encoders so both share same base address but with + * its own different sub block address. + */ +static const struct dpu_dsc_cfg glymur_dsc[] = { + { + .name = "dce_0_0", .id = DSC_0, + .base = 0x80000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_0_1", .id = DSC_1, + .base = 0x80000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_1_0", .id = DSC_2, + .base = 0x81000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_1_1", .id = DSC_3, + .base = 0x81000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_2_0", .id = DSC_4, + .base = 0x82000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_2_1", .id = DSC_5, + .base = 0x82000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_3_0", .id = DSC_6, + .base = 0x83000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_3_1", .id = DSC_7, + .base = 0x83000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, + +}; + +static const struct dpu_wb_cfg glymur_wb[] = { + { + .name = "wb_2", .id = WB_2, + .base = 0x65000, .len = 0x2c8, + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), + .xin_id = 6, + .vbif_idx = VBIF_RT, + .maxlinewidth = 4096, + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), + }, +}; + +static const struct dpu_cwb_cfg glymur_cwb[] = { + { + .name = "cwb_0", .id = CWB_0, + .base = 0x66200, .len = 0x20, + }, + { + .name = "cwb_1", .id = CWB_1, + .base = 0x66600, .len = 0x20, + }, + { + .name = "cwb_2", .id = CWB_2, + .base = 0x7e200, .len = 0x20, + }, + { + .name = "cwb_3", .id = CWB_3, + .base = 0x7e600, .len = 0x20, + }, +}; + +static const struct dpu_intf_cfg glymur_intf[] = { + { + .name = "intf_0", .id = INTF_0, + .base = 0x34000, .len = 0x400, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .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), + }, { + .name = "intf_1", .id = INTF_1, + .base = 0x35000, .len = 0x400, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_0, + .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 = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2), + }, { + .name = "intf_2", .id = INTF_2, + .base = 0x36000, .len = 0x400, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_1, + .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 = DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2), + }, { + .name = "intf_3", .id = INTF_3, + .base = 0x37000, .len = 0x400, + .type = INTF_NONE, + .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ + .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), + }, { + .name = "intf_4", .id = INTF_4, + .base = 0x38000, .len = 0x400, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, + .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), + }, { + .name = "intf_5", .id = INTF_5, + .base = 0x39000, .len = 0x400, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_3, + .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), + }, { + .name = "intf_6", .id = INTF_6, + .base = 0x3A000, .len = 0x400, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_2, + .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), + }, { + .name = "intf_7", .id = INTF_7, + .base = 0x3b000, .len = 0x400, + .type = INTF_NONE, + .controller_id = MSM_DP_CONTROLLER_2, /* pair with intf_6 for DP MST */ + .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), + }, { + .name = "intf_8", .id = INTF_8, + .base = 0x3c000, .len = 0x400, + .type = INTF_NONE, + .controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_4 for DP MST */ + .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), + }, +}; + +static const struct dpu_perf_cfg glymur_perf_data = { + .max_bw_low = 18900000, + .max_bw_high = 28500000, + .min_core_ib = 2500000, + .min_llcc_ib = 0, + .min_dram_ib = 800000, + .min_prefill_lines = 35, + .danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0}, + .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(sc7180_qos_linear), + .entries = sc7180_qos_linear + }, + {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), + .entries = sc7180_qos_macrotile + }, + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), + .entries = sc7180_qos_nrt + }, + /* TODO: macrotile-qseed is different from macrotile */ + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; + +static const struct dpu_mdss_version glymur_mdss_ver = { + .core_major_ver = 12, + .core_minor_ver = 2, +}; + +const struct dpu_mdss_cfg dpu_glymur_cfg = { + .mdss_ver = &glymur_mdss_ver, + .caps = &glymur_dpu_caps, + .mdp = &glymur_mdp, + .cdm = &dpu_cdm_5_x, + .ctl_count = ARRAY_SIZE(glymur_ctl), + .ctl = glymur_ctl, + .sspp_count = ARRAY_SIZE(glymur_sspp), + .sspp = glymur_sspp, + .mixer_count = ARRAY_SIZE(glymur_lm), + .mixer = glymur_lm, + .dspp_count = ARRAY_SIZE(glymur_dspp), + .dspp = glymur_dspp, + .pingpong_count = ARRAY_SIZE(glymur_pp), + .pingpong = glymur_pp, + .dsc_count = ARRAY_SIZE(glymur_dsc), + .dsc = glymur_dsc, + .merge_3d_count = ARRAY_SIZE(glymur_merge_3d), + .merge_3d = glymur_merge_3d, + .wb_count = ARRAY_SIZE(glymur_wb), + .wb = glymur_wb, + .cwb_count = ARRAY_SIZE(glymur_cwb), + .cwb = sm8650_cwb, + .intf_count = ARRAY_SIZE(glymur_intf), + .intf = glymur_intf, + .vbif_count = ARRAY_SIZE(sm8650_vbif), + .vbif = sm8650_vbif, + .perf = &glymur_perf_data, +}; + +#endif diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h index ab3dfb0b374e..29e0eba91930 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h @@ -19,7 +19,6 @@ static const struct dpu_mdp_cfg msm8937_mdp[] = { { .name = "top_0", .base = 0x0, .len = 0x454, - .features = BIT(DPU_MDP_VSYNC_SEL), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 }, @@ -100,14 +99,12 @@ static const struct dpu_pingpong_cfg msm8937_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), @@ -118,7 +115,6 @@ static const struct dpu_dspp_cfg msm8937_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &msm8998_dspp_sblk, }, }; @@ -132,7 +128,6 @@ static const struct dpu_intf_cfg msm8937_intf[] = { .prog_fetch_lines_worst_case = 14, .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 = 0x268, @@ -141,7 +136,6 @@ static const struct dpu_intf_cfg msm8937_intf[] = { .prog_fetch_lines_worst_case = 14, .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, }, }; @@ -190,6 +184,7 @@ const struct dpu_mdss_cfg dpu_msm8937_cfg = { .mdss_ver = &msm8937_mdss_ver, .caps = &msm8937_dpu_caps, .mdp = msm8937_mdp, + .cdm = &dpu_cdm_1_x_4_x, .ctl_count = ARRAY_SIZE(msm8937_ctl), .ctl = msm8937_ctl, .sspp_count = ARRAY_SIZE(msm8937_sspp), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h index 6bdaecca6761..cb1ee4b63f9f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h @@ -19,7 +19,6 @@ static const struct dpu_mdp_cfg msm8917_mdp[] = { { .name = "top_0", .base = 0x0, .len = 0x454, - .features = BIT(DPU_MDP_VSYNC_SEL), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 }, @@ -93,7 +92,6 @@ static const struct dpu_pingpong_cfg msm8917_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), @@ -104,7 +102,6 @@ static const struct dpu_dspp_cfg msm8917_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &msm8998_dspp_sblk, }, }; @@ -118,7 +115,6 @@ static const struct dpu_intf_cfg msm8917_intf[] = { .prog_fetch_lines_worst_case = 14, .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, }, }; @@ -167,6 +163,7 @@ const struct dpu_mdss_cfg dpu_msm8917_cfg = { .mdss_ver = &msm8917_mdss_ver, .caps = &msm8917_dpu_caps, .mdp = msm8917_mdp, + .cdm = &dpu_cdm_1_x_4_x, .ctl_count = ARRAY_SIZE(msm8917_ctl), .ctl = msm8917_ctl, .sspp_count = ARRAY_SIZE(msm8917_sspp), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h index 14f36ea6ad0e..b44d02b48418 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h @@ -19,7 +19,6 @@ static const struct dpu_mdp_cfg msm8953_mdp[] = { { .name = "top_0", .base = 0x0, .len = 0x454, - .features = BIT(DPU_MDP_VSYNC_SEL), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 }, @@ -100,14 +99,12 @@ static const struct dpu_pingpong_cfg msm8953_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), @@ -118,7 +115,6 @@ static const struct dpu_dspp_cfg msm8953_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &msm8998_dspp_sblk, }, }; @@ -131,7 +127,6 @@ static const struct dpu_intf_cfg msm8953_intf[] = { .prog_fetch_lines_worst_case = 14, .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 = 0x268, @@ -140,7 +135,6 @@ static const struct dpu_intf_cfg msm8953_intf[] = { .prog_fetch_lines_worst_case = 14, .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 = 0x268, @@ -149,7 +143,6 @@ static const struct dpu_intf_cfg msm8953_intf[] = { .prog_fetch_lines_worst_case = 14, .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, }, }; @@ -198,6 +191,7 @@ const struct dpu_mdss_cfg dpu_msm8953_cfg = { .mdss_ver = &msm8953_mdss_ver, .caps = &msm8953_dpu_caps, .mdp = msm8953_mdp, + .cdm = &dpu_cdm_1_x_4_x, .ctl_count = ARRAY_SIZE(msm8953_ctl), .ctl = msm8953_ctl, .sspp_count = ARRAY_SIZE(msm8953_sspp), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h index 491f6f5827d1..8af63db315b4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h @@ -22,7 +22,6 @@ static const struct dpu_mdp_cfg msm8996_mdp[] = { { .name = "top_0", .base = 0x0, .len = 0x454, - .features = BIT(DPU_MDP_VSYNC_SEL), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, @@ -181,28 +180,24 @@ static const struct dpu_pingpong_cfg msm8996_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_MSM8996_TE2_MASK, - .sblk = &msm8996_pp_sblk_te, + .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_MSM8996_TE2_MASK, - .sblk = &msm8996_pp_sblk_te, + .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x71800, .len = 0xd4, - .features = PINGPONG_MSM8996_MASK, .sblk = &msm8996_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15), @@ -223,12 +218,10 @@ static const struct dpu_dspp_cfg msm8996_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &msm8998_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &msm8998_dspp_sblk, }, }; @@ -241,7 +234,6 @@ static const struct dpu_intf_cfg msm8996_intf[] = { .prog_fetch_lines_worst_case = 25, .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 = 0x268, @@ -250,7 +242,6 @@ static const struct dpu_intf_cfg msm8996_intf[] = { .prog_fetch_lines_worst_case = 25, .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 = 0x268, @@ -259,7 +250,6 @@ static const struct dpu_intf_cfg msm8996_intf[] = { .prog_fetch_lines_worst_case = 25, .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 = 0x268, @@ -267,7 +257,6 @@ static const struct dpu_intf_cfg msm8996_intf[] = { .prog_fetch_lines_worst_case = 25, .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, }, }; @@ -316,6 +305,7 @@ const struct dpu_mdss_cfg dpu_msm8996_cfg = { .mdss_ver = &msm8996_mdss_ver, .caps = &msm8996_dpu_caps, .mdp = msm8996_mdp, + .cdm = &dpu_cdm_1_x_4_x, .ctl_count = ARRAY_SIZE(msm8996_ctl), .ctl = msm8996_ctl, .sspp_count = ARRAY_SIZE(msm8996_sspp), 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 64c94e919a69..f91220496082 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 @@ -23,7 +23,6 @@ static const struct dpu_caps msm8998_dpu_caps = { static const struct dpu_mdp_cfg msm8998_mdp = { .name = "top_0", .base = 0x0, .len = 0x458, - .features = BIT(DPU_MDP_VSYNC_SEL), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, @@ -170,28 +169,24 @@ static const struct dpu_pingpong_cfg msm8998_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, - .features = PINGPONG_SDM845_MASK, .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x71800, .len = 0xd4, - .features = PINGPONG_SDM845_MASK, .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15), @@ -212,12 +207,10 @@ static const struct dpu_dspp_cfg msm8998_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &msm8998_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &msm8998_dspp_sblk, }, }; @@ -302,6 +295,7 @@ const struct dpu_mdss_cfg dpu_msm8998_cfg = { .mdss_ver = &msm8998_mdss_ver, .caps = &msm8998_dpu_caps, .mdp = &msm8998_mdp, + .cdm = &dpu_cdm_1_x_4_x, .ctl_count = ARRAY_SIZE(msm8998_ctl), .ctl = msm8998_ctl, .sspp_count = ARRAY_SIZE(msm8998_sspp), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h index 424815e7fb7d..8f9a097147c0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h @@ -22,7 +22,6 @@ static const struct dpu_caps sdm660_dpu_caps = { static const struct dpu_mdp_cfg sdm660_mdp = { .name = "top_0", .base = 0x0, .len = 0x458, - .features = BIT(DPU_MDP_VSYNC_SEL), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, @@ -141,28 +140,24 @@ static const struct dpu_pingpong_cfg sdm660_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, - .features = PINGPONG_SDM845_MASK, .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x71800, .len = 0xd4, - .features = PINGPONG_SDM845_MASK, .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15), @@ -183,12 +178,10 @@ static const struct dpu_dspp_cfg sdm660_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &msm8998_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &msm8998_dspp_sblk, }, }; @@ -202,7 +195,6 @@ static const struct dpu_intf_cfg sdm660_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, @@ -211,7 +203,6 @@ static const struct dpu_intf_cfg sdm660_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, @@ -220,7 +211,6 @@ static const struct dpu_intf_cfg sdm660_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, }, }; @@ -269,6 +259,7 @@ const struct dpu_mdss_cfg dpu_sdm660_cfg = { .mdss_ver = &sdm660_mdss_ver, .caps = &sdm660_dpu_caps, .mdp = &sdm660_mdp, + .cdm = &dpu_cdm_1_x_4_x, .ctl_count = ARRAY_SIZE(sdm660_ctl), .ctl = sdm660_ctl, .sspp_count = ARRAY_SIZE(sdm660_sspp), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h index df01227fc364..0ad18bd273ff 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h @@ -22,7 +22,6 @@ static const struct dpu_caps sdm630_dpu_caps = { static const struct dpu_mdp_cfg sdm630_mdp = { .name = "top_0", .base = 0x0, .len = 0x458, - .features = BIT(DPU_MDP_VSYNC_SEL), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, @@ -115,14 +114,12 @@ static const struct dpu_pingpong_cfg sdm630_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, - .features = PINGPONG_SDM845_MASK, .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14), @@ -133,7 +130,6 @@ static const struct dpu_dspp_cfg sdm630_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &msm8998_dspp_sblk, }, }; @@ -147,7 +143,6 @@ static const struct dpu_intf_cfg sdm630_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, @@ -156,7 +151,6 @@ static const struct dpu_intf_cfg sdm630_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, }, }; @@ -205,6 +199,7 @@ const struct dpu_mdss_cfg dpu_sdm630_cfg = { .mdss_ver = &sdm630_mdss_ver, .caps = &sdm630_dpu_caps, .mdp = &sdm630_mdp, + .cdm = &dpu_cdm_1_x_4_x, .ctl_count = ARRAY_SIZE(sdm630_ctl), .ctl = sdm630_ctl, .sspp_count = ARRAY_SIZE(sdm630_sspp), 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 72bd4f7e9e50..5cc9f55d542b 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 @@ -23,7 +23,6 @@ static const struct dpu_caps sdm845_dpu_caps = { static const struct dpu_mdp_cfg sdm845_mdp = { .name = "top_0", .base = 0x0, .len = 0x45c, - .features = BIT(DPU_MDP_AUDIO_SELECT) | BIT(DPU_MDP_VSYNC_SEL), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, @@ -134,7 +133,7 @@ static const struct dpu_lm_cfg sdm845_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -142,7 +141,7 @@ static const struct dpu_lm_cfg sdm845_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -150,7 +149,7 @@ static const struct dpu_lm_cfg sdm845_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_5, .pingpong = PINGPONG_2, @@ -158,7 +157,7 @@ static const struct dpu_lm_cfg sdm845_lm[] = { }, { .name = "lm_5", .id = LM_5, .base = 0x49000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, @@ -170,22 +169,18 @@ static const struct dpu_dspp_cfg sdm845_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_2", .id = DSPP_2, .base = 0x58000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_3", .id = DSPP_3, .base = 0x5a000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -194,28 +189,24 @@ static const struct dpu_pingpong_cfg sdm845_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SDM845_TE2_MASK, - .sblk = &sdm845_pp_sblk_te, + .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, - .features = PINGPONG_SDM845_MASK, .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x71800, .len = 0xd4, - .features = PINGPONG_SDM845_MASK, .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15), @@ -319,6 +310,7 @@ const struct dpu_mdss_cfg dpu_sdm845_cfg = { .mdss_ver = &sdm845_mdss_ver, .caps = &sdm845_dpu_caps, .mdp = &sdm845_mdp, + .cdm = &dpu_cdm_1_x_4_x, .ctl_count = ARRAY_SIZE(sdm845_ctl), .ctl = sdm845_ctl, .sspp_count = ARRAY_SIZE(sdm845_sspp), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_1_sdm670.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_1_sdm670.h index cbbdaebe357e..0f5e9babdeea 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_1_sdm670.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_1_sdm670.h @@ -11,7 +11,6 @@ static const struct dpu_mdp_cfg sdm670_mdp = { .name = "top_0", .base = 0x0, .len = 0x45c, - .features = BIT(DPU_MDP_AUDIO_SELECT), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, @@ -65,6 +64,52 @@ static const struct dpu_sspp_cfg sdm670_sspp[] = { }, }; +static const struct dpu_lm_cfg sdm670_lm[] = { + { + .name = "lm_0", .id = LM_0, + .base = 0x44000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_1, + .pingpong = PINGPONG_0, + .dspp = DSPP_0, + }, { + .name = "lm_1", .id = LM_1, + .base = 0x45000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_0, + .pingpong = PINGPONG_1, + .dspp = DSPP_1, + }, { + .name = "lm_2", .id = LM_2, + .base = 0x46000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_5, + .pingpong = PINGPONG_2, + }, { + .name = "lm_5", .id = LM_5, + .base = 0x49000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_2, + .pingpong = PINGPONG_3, + }, +}; + +static const struct dpu_dspp_cfg sdm670_dspp[] = { + { + .name = "dspp_0", .id = DSPP_0, + .base = 0x54000, .len = 0x1800, + .sblk = &sdm845_dspp_sblk, + }, { + .name = "dspp_1", .id = DSPP_1, + .base = 0x56000, .len = 0x1800, + .sblk = &sdm845_dspp_sblk, + }, +}; + static const struct dpu_dsc_cfg sdm670_dsc[] = { { .name = "dsc_0", .id = DSC_0, @@ -84,12 +129,15 @@ const struct dpu_mdss_cfg dpu_sdm670_cfg = { .mdss_ver = &sdm670_mdss_ver, .caps = &sdm845_dpu_caps, .mdp = &sdm670_mdp, + .cdm = &dpu_cdm_1_x_4_x, .ctl_count = ARRAY_SIZE(sdm845_ctl), .ctl = sdm845_ctl, .sspp_count = ARRAY_SIZE(sdm670_sspp), .sspp = sdm670_sspp, - .mixer_count = ARRAY_SIZE(sdm845_lm), - .mixer = sdm845_lm, + .mixer_count = ARRAY_SIZE(sdm670_lm), + .mixer = sdm670_lm, + .dspp_count = ARRAY_SIZE(sdm670_dspp), + .dspp = sdm670_dspp, .pingpong_count = ARRAY_SIZE(sdm845_pp), .pingpong = sdm845_pp, .dsc_count = ARRAY_SIZE(sdm670_dsc), 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 6ccfde82fecd..ae1b2ed96e9f 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 @@ -23,7 +23,6 @@ static const struct dpu_caps sm8150_dpu_caps = { static const struct dpu_mdp_cfg sm8150_mdp = { .name = "top_0", .base = 0x0, .len = 0x45c, - .features = BIT(DPU_MDP_AUDIO_SELECT), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, @@ -37,37 +36,30 @@ static const struct dpu_mdp_cfg sm8150_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8150_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x1200, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x1400, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x1600, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x1800, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a00, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -76,7 +68,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -84,7 +76,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 4, .type = SSPP_TYPE_VIG, @@ -92,7 +84,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 8, .type = SSPP_TYPE_VIG, @@ -100,7 +92,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 12, .type = SSPP_TYPE_VIG, @@ -108,7 +100,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -116,7 +108,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -124,7 +116,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x1f0, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, @@ -132,7 +124,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { }, { .name = "sspp_11", .id = SSPP_DMA3, .base = 0x2a000, .len = 0x1f0, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 13, .type = SSPP_TYPE_DMA, @@ -144,7 +136,7 @@ static const struct dpu_lm_cfg sm8150_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -152,7 +144,7 @@ static const struct dpu_lm_cfg sm8150_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -160,28 +152,30 @@ static const struct dpu_lm_cfg sm8150_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, + .dspp = DSPP_2, }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, + .dspp = DSPP_3, }, { .name = "lm_4", .id = LM_4, .base = 0x48000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_5, .pingpong = PINGPONG_4, }, { .name = "lm_5", .id = LM_5, .base = 0x49000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_4, .pingpong = PINGPONG_5, @@ -192,22 +186,18 @@ static const struct dpu_dspp_cfg sm8150_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_2", .id = DSPP_2, .base = 0x58000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_3", .id = DSPP_3, .base = 0x5a000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -216,42 +206,36 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x71800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x72000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x72800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), @@ -275,19 +259,15 @@ static const struct dpu_dsc_cfg sm8150_dsc[] = { { .name = "dsc_0", .id = DSC_0, .base = 0x80000, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_1", .id = DSC_1, .base = 0x80400, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_2", .id = DSC_2, .base = 0x80800, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_3", .id = DSC_3, .base = 0x80c00, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, }; @@ -296,8 +276,8 @@ static const struct dpu_wb_cfg sm8150_wb[] = { .name = "wb_2", .id = WB_2, .base = 0x65000, .len = 0x2c8, .features = WB_SDM845_MASK, - .format_list = wb2_formats_rgb, - .num_formats = ARRAY_SIZE(wb2_formats_rgb), + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .clk_ctrl = DPU_CLK_CTRL_WB2, .xin_id = 6, .vbif_idx = VBIF_RT, @@ -310,7 +290,6 @@ static const struct dpu_intf_cfg sm8150_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x6a000, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -319,7 +298,6 @@ static const struct dpu_intf_cfg sm8150_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2bc, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -329,7 +307,6 @@ static const struct dpu_intf_cfg sm8150_intf[] = { }, { .name = "intf_2", .id = INTF_2, .base = 0x6b000, .len = 0x2bc, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -339,7 +316,6 @@ static const struct dpu_intf_cfg sm8150_intf[] = { }, { .name = "intf_3", .id = INTF_3, .base = 0x6b800, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -386,6 +362,7 @@ const struct dpu_mdss_cfg dpu_sm8150_cfg = { .mdss_ver = &sm8150_mdss_ver, .caps = &sm8150_dpu_caps, .mdp = &sm8150_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sm8150_ctl), .ctl = sm8150_ctl, .sspp_count = ARRAY_SIZE(sm8150_sspp), 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 bab19ddd1d4f..b572cfa7ed35 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 @@ -23,7 +23,6 @@ static const struct dpu_caps sc8180x_dpu_caps = { static const struct dpu_mdp_cfg sc8180x_mdp = { .name = "top_0", .base = 0x0, .len = 0x45c, - .features = BIT(DPU_MDP_AUDIO_SELECT), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, @@ -41,32 +40,26 @@ static const struct dpu_ctl_cfg sc8180x_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x1200, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x1400, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x1600, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x1800, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a00, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -75,7 +68,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -83,7 +76,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 4, .type = SSPP_TYPE_VIG, @@ -91,7 +84,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 8, .type = SSPP_TYPE_VIG, @@ -99,7 +92,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_1_4, .xin_id = 12, .type = SSPP_TYPE_VIG, @@ -107,7 +100,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -115,7 +108,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -123,7 +116,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x1f0, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, @@ -131,7 +124,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { }, { .name = "sspp_11", .id = SSPP_DMA3, .base = 0x2a000, .len = 0x1f0, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 13, .type = SSPP_TYPE_DMA, @@ -143,7 +136,7 @@ static const struct dpu_lm_cfg sc8180x_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -151,7 +144,7 @@ static const struct dpu_lm_cfg sc8180x_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -159,28 +152,30 @@ static const struct dpu_lm_cfg sc8180x_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, + .dspp = DSPP_2, }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, + .dspp = DSPP_3, }, { .name = "lm_4", .id = LM_4, .base = 0x48000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_5, .pingpong = PINGPONG_4, }, { .name = "lm_5", .id = LM_5, .base = 0x49000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_4, .pingpong = PINGPONG_5, @@ -191,22 +186,18 @@ static const struct dpu_dspp_cfg sc8180x_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_2", .id = DSPP_2, .base = 0x58000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_3", .id = DSPP_3, .base = 0x5a000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -215,42 +206,36 @@ static const struct dpu_pingpong_cfg sc8180x_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x71800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x72000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x72800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), @@ -274,27 +259,21 @@ static const struct dpu_dsc_cfg sc8180x_dsc[] = { { .name = "dsc_0", .id = DSC_0, .base = 0x80000, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_1", .id = DSC_1, .base = 0x80400, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_2", .id = DSC_2, .base = 0x80800, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_3", .id = DSC_3, .base = 0x80c00, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_4", .id = DSC_4, .base = 0x81000, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_5", .id = DSC_5, .base = 0x81400, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, }; @@ -303,8 +282,8 @@ static const struct dpu_wb_cfg sc8180x_wb[] = { .name = "wb_2", .id = WB_2, .base = 0x65000, .len = 0x2c8, .features = WB_SDM845_MASK, - .format_list = wb2_formats_rgb, - .num_formats = ARRAY_SIZE(wb2_formats_rgb), + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .clk_ctrl = DPU_CLK_CTRL_WB2, .xin_id = 6, .vbif_idx = VBIF_RT, @@ -317,7 +296,6 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x6a000, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -326,7 +304,6 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2bc, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -336,7 +313,6 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { }, { .name = "intf_2", .id = INTF_2, .base = 0x6b000, .len = 0x2bc, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -348,7 +324,6 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { { .name = "intf_3", .id = INTF_3, .base = 0x6b800, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = 999, .prog_fetch_lines_worst_case = 24, @@ -357,7 +332,6 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { }, { .name = "intf_4", .id = INTF_4, .base = 0x6c000, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -366,7 +340,6 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { }, { .name = "intf_5", .id = INTF_5, .base = 0x6c800, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_2, .prog_fetch_lines_worst_case = 24, @@ -381,6 +354,7 @@ static const struct dpu_perf_cfg sc8180x_perf_data = { .min_core_ib = 2400000, .min_llcc_ib = 800000, .min_dram_ib = 800000, + .min_prefill_lines = 24, .danger_lut_tbl = {0xf, 0xffff, 0x0}, .safe_lut_tbl = {0xfff0, 0xf000, 0xffff}, .qos_lut_tbl = { @@ -412,6 +386,7 @@ const struct dpu_mdss_cfg dpu_sc8180x_cfg = { .mdss_ver = &sc8180x_mdss_ver, .caps = &sc8180x_dpu_caps, .mdp = &sc8180x_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sc8180x_ctl), .ctl = sc8180x_ctl, .sspp_count = ARRAY_SIZE(sc8180x_sspp), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h index 2fe674d1e059..a56c288ac10c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h @@ -23,7 +23,6 @@ static const struct dpu_caps sm7150_dpu_caps = { static const struct dpu_mdp_cfg sm7150_mdp = { .name = "top_0", .base = 0x0, .len = 0x45c, - .features = BIT(DPU_MDP_AUDIO_SELECT), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, @@ -38,32 +37,26 @@ static const struct dpu_ctl_cfg sm7150_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x1200, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x1400, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x1600, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x1800, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a00, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -72,7 +65,7 @@ static const struct dpu_sspp_cfg sm7150_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_2_4, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -80,7 +73,7 @@ static const struct dpu_sspp_cfg sm7150_sspp[] = { }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_2_4, .xin_id = 4, .type = SSPP_TYPE_VIG, @@ -88,7 +81,7 @@ static const struct dpu_sspp_cfg sm7150_sspp[] = { }, { .name = "sspp_2", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -96,7 +89,7 @@ static const struct dpu_sspp_cfg sm7150_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -104,7 +97,7 @@ static const struct dpu_sspp_cfg sm7150_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x1f0, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, @@ -116,7 +109,7 @@ static const struct dpu_lm_cfg sm7150_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -124,7 +117,7 @@ static const struct dpu_lm_cfg sm7150_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -132,14 +125,14 @@ static const struct dpu_lm_cfg sm7150_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, @@ -150,12 +143,10 @@ static const struct dpu_dspp_cfg sm7150_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -164,28 +155,24 @@ static const struct dpu_pingpong_cfg sm7150_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x71800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), @@ -206,11 +193,9 @@ static const struct dpu_dsc_cfg sm7150_dsc[] = { { .name = "dsc_0", .id = DSC_0, .base = 0x80000, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_1", .id = DSC_1, .base = 0x80400, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, }; @@ -218,7 +203,6 @@ static const struct dpu_intf_cfg sm7150_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x6a000, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -227,7 +211,6 @@ static const struct dpu_intf_cfg sm7150_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2bc, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -237,7 +220,6 @@ static const struct dpu_intf_cfg sm7150_intf[] = { }, { .name = "intf_2", .id = INTF_2, .base = 0x6b000, .len = 0x2bc, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -247,7 +229,6 @@ static const struct dpu_intf_cfg sm7150_intf[] = { }, { .name = "intf_3", .id = INTF_3, .base = 0x6b800, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -260,9 +241,9 @@ static const struct dpu_wb_cfg sm7150_wb[] = { { .name = "wb_2", .id = WB_2, .base = 0x65000, .len = 0x2c8, - .features = WB_SM8250_MASK, - .format_list = wb2_formats_rgb, - .num_formats = ARRAY_SIZE(wb2_formats_rgb), + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .clk_ctrl = DPU_CLK_CTRL_WB2, .xin_id = 6, .vbif_idx = VBIF_RT, @@ -309,6 +290,7 @@ const struct dpu_mdss_cfg dpu_sm7150_cfg = { .mdss_ver = &sm7150_mdss_ver, .caps = &sm7150_dpu_caps, .mdp = &sm7150_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sm7150_ctl), .ctl = sm7150_ctl, .sspp_count = ARRAY_SIZE(sm7150_sspp), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h new file mode 100644 index 000000000000..26883f6b66b3 --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h @@ -0,0 +1,254 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _DPU_5_3_SM6150_H +#define _DPU_5_3_SM6150_H + +static const struct dpu_caps sm6150_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0x9, + .has_dim_layer = true, + .has_idle_pc = true, + .max_linewidth = 2160, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .max_hdeci_exp = MAX_HORZ_DECIMATION, + .max_vdeci_exp = MAX_VERT_DECIMATION, +}; + +static const struct dpu_mdp_cfg sm6150_mdp = { + .name = "top_0", + .base = 0x0, .len = 0x45c, + .clk_ctrls = { + [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, + [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, + [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 }, + }, +}; + +static const struct dpu_ctl_cfg sm6150_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x1000, .len = 0x1e0, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, { + .name = "ctl_1", .id = CTL_1, + .base = 0x1200, .len = 0x1e0, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, { + .name = "ctl_2", .id = CTL_2, + .base = 0x1400, .len = 0x1e0, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, { + .name = "ctl_3", .id = CTL_3, + .base = 0x1600, .len = 0x1e0, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, { + .name = "ctl_4", .id = CTL_4, + .base = 0x1800, .len = 0x1e0, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, { + .name = "ctl_5", .id = CTL_5, + .base = 0x1a00, .len = 0x1e0, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), + }, +}; + +static const struct dpu_sspp_cfg sm6150_sspp[] = { + { + .name = "sspp_0", .id = SSPP_VIG0, + .base = 0x4000, .len = 0x1f0, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_2_4, + .xin_id = 0, + .type = SSPP_TYPE_VIG, + .clk_ctrl = DPU_CLK_CTRL_VIG0, + }, { + .name = "sspp_8", .id = SSPP_DMA0, + .base = 0x24000, .len = 0x1f0, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 1, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA0, + }, { + .name = "sspp_9", .id = SSPP_DMA1, + .base = 0x26000, .len = 0x1f0, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 5, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA1, + }, { + .name = "sspp_10", .id = SSPP_DMA2, + .base = 0x28000, .len = 0x1f0, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 9, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA2, + }, { + .name = "sspp_11", .id = SSPP_DMA3, + .base = 0x2a000, .len = 0x1f0, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 13, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA3, + }, +}; + +static const struct dpu_lm_cfg sm6150_lm[] = { + { + .name = "lm_0", .id = LM_0, + .base = 0x44000, .len = 0x320, + .sblk = &sdm845_lm_sblk, + .pingpong = PINGPONG_0, + .dspp = DSPP_0, + }, { + .name = "lm_1", .id = LM_1, + .base = 0x45000, .len = 0x320, + .sblk = &sdm845_lm_sblk, + .pingpong = PINGPONG_1, + }, { + .name = "lm_2", .id = LM_2, + .base = 0x46000, .len = 0x320, + .sblk = &sdm845_lm_sblk, + .pingpong = PINGPONG_2, + }, +}; + +static const struct dpu_dspp_cfg sm6150_dspp[] = { + { + .name = "dspp_0", .id = DSPP_0, + .base = 0x54000, .len = 0x1800, + .sblk = &sdm845_dspp_sblk, + }, +}; + +static const struct dpu_pingpong_cfg sm6150_pp[] = { + { + .name = "pingpong_0", .id = PINGPONG_0, + .base = 0x70000, .len = 0xd4, + .sblk = &sdm845_pp_sblk, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + }, { + .name = "pingpong_1", .id = PINGPONG_1, + .base = 0x70800, .len = 0xd4, + .sblk = &sdm845_pp_sblk, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), + }, { + .name = "pingpong_2", .id = PINGPONG_2, + .base = 0x71000, .len = 0xd4, + .sblk = &sdm845_pp_sblk, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + }, +}; + +static const struct dpu_wb_cfg sm6150_wb[] = { + { + .name = "wb_2", .id = WB_2, + .base = 0x65000, .len = 0x2c8, + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), + .clk_ctrl = DPU_CLK_CTRL_WB2, + .xin_id = 6, + .vbif_idx = VBIF_RT, + .maxlinewidth = 2160, + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), + }, +}; + +static const struct dpu_intf_cfg sm6150_intf[] = { + { + .name = "intf_0", .id = INTF_0, + .base = 0x6a000, .len = 0x280, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .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), + }, { + .name = "intf_1", .id = INTF_1, + .base = 0x6a800, .len = 0x2c0, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_0, + .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 = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2), + }, { + .name = "intf_3", .id = INTF_3, + .base = 0x6b800, .len = 0x280, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, + .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), + }, +}; + +static const struct dpu_perf_cfg sm6150_perf_data = { + .max_bw_low = 4800000, + .max_bw_high = 4800000, + .min_core_ib = 2400000, + .min_llcc_ib = 0, + .min_dram_ib = 800000, + .min_prefill_lines = 24, + .danger_lut_tbl = {0xf, 0xffff, 0x0}, + .safe_lut_tbl = {0xfff8, 0xf000, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(sm8150_qos_linear), + .entries = sm8150_qos_linear + }, + {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), + .entries = sc7180_qos_macrotile + }, + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), + .entries = sc7180_qos_nrt + }, + /* TODO: macrotile-qseed is different from macrotile */ + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; + +static const struct dpu_mdss_version sm6150_mdss_ver = { + .core_major_ver = 5, + .core_minor_ver = 3, +}; + +const struct dpu_mdss_cfg dpu_sm6150_cfg = { + .mdss_ver = &sm6150_mdss_ver, + .caps = &sm6150_dpu_caps, + .mdp = &sm6150_mdp, + .cdm = &dpu_cdm_5_x, + .ctl_count = ARRAY_SIZE(sm6150_ctl), + .ctl = sm6150_ctl, + .sspp_count = ARRAY_SIZE(sm6150_sspp), + .sspp = sm6150_sspp, + .mixer_count = ARRAY_SIZE(sm6150_lm), + .mixer = sm6150_lm, + .dspp_count = ARRAY_SIZE(sm6150_dspp), + .dspp = sm6150_dspp, + .pingpong_count = ARRAY_SIZE(sm6150_pp), + .pingpong = sm6150_pp, + .wb_count = ARRAY_SIZE(sm6150_wb), + .wb = sm6150_wb, + .intf_count = ARRAY_SIZE(sm6150_intf), + .intf = sm6150_intf, + .vbif_count = ARRAY_SIZE(sdm845_vbif), + .vbif = sdm845_vbif, + .perf = &sm6150_perf_data, +}; + +#endif 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 d039b96beb97..fbf50f279e66 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 @@ -22,7 +22,6 @@ static const struct dpu_caps sm6125_dpu_caps = { static const struct dpu_mdp_cfg sm6125_mdp = { .name = "top_0", .base = 0x0, .len = 0x45c, - .features = 0, .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, @@ -35,32 +34,26 @@ static const struct dpu_ctl_cfg sm6125_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x1200, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x1400, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x1600, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x1800, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a00, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -69,7 +62,7 @@ static const struct dpu_sspp_cfg sm6125_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f0, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_2_4, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -77,7 +70,7 @@ static const struct dpu_sspp_cfg sm6125_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -85,7 +78,7 @@ static const struct dpu_sspp_cfg sm6125_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f0, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -97,7 +90,6 @@ static const struct dpu_lm_cfg sm6125_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_QCM2290_MASK, .sblk = &sdm845_lm_sblk, .pingpong = PINGPONG_0, .dspp = DSPP_0, @@ -105,7 +97,6 @@ static const struct dpu_lm_cfg sm6125_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_QCM2290_MASK, .sblk = &sdm845_lm_sblk, .pingpong = PINGPONG_1, .dspp = 0, @@ -117,7 +108,6 @@ static const struct dpu_dspp_cfg sm6125_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -126,14 +116,12 @@ static const struct dpu_pingpong_cfg sm6125_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .merge_3d = 0, .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .merge_3d = 0, .sblk = &sdm845_pp_sblk, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), @@ -145,8 +133,8 @@ static const struct dpu_wb_cfg sm6125_wb[] = { .name = "wb_2", .id = WB_2, .base = 0x65000, .len = 0x2c8, .features = WB_SDM845_MASK, - .format_list = wb2_formats_rgb, - .num_formats = ARRAY_SIZE(wb2_formats_rgb), + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .clk_ctrl = DPU_CLK_CTRL_WB2, .xin_id = 6, .vbif_idx = VBIF_RT, @@ -159,7 +147,6 @@ static const struct dpu_intf_cfg sm6125_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x6a000, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -168,7 +155,6 @@ static const struct dpu_intf_cfg sm6125_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2c0, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = 0, .prog_fetch_lines_worst_case = 24, @@ -216,6 +202,7 @@ const struct dpu_mdss_cfg dpu_sm6125_cfg = { .mdss_ver = &sm6125_mdss_ver, .caps = &sm6125_dpu_caps, .mdp = &sm6125_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sm6125_ctl), .ctl = sm6125_ctl, .sspp_count = ARRAY_SIZE(sm6125_sspp), 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 a57d50b1f028..7b8b7a1c2d76 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 @@ -35,37 +35,30 @@ static const struct dpu_mdp_cfg sm8250_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8250_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x1200, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x1400, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x1600, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x1800, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a00, .len = 0x1e0, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -142,7 +135,7 @@ static const struct dpu_lm_cfg sm8250_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -150,7 +143,7 @@ static const struct dpu_lm_cfg sm8250_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -158,28 +151,30 @@ static const struct dpu_lm_cfg sm8250_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, + .dspp = DSPP_2, }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, + .dspp = DSPP_3, }, { .name = "lm_4", .id = LM_4, .base = 0x48000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_5, .pingpong = PINGPONG_4, }, { .name = "lm_5", .id = LM_5, .base = 0x49000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_4, .pingpong = PINGPONG_5, @@ -190,22 +185,18 @@ static const struct dpu_dspp_cfg sm8250_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_2", .id = DSPP_2, .base = 0x58000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_3", .id = DSPP_3, .base = 0x5a000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -214,42 +205,36 @@ static const struct dpu_pingpong_cfg sm8250_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x71000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x71800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x72000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x72800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), @@ -273,19 +258,15 @@ static const struct dpu_dsc_cfg sm8250_dsc[] = { { .name = "dsc_0", .id = DSC_0, .base = 0x80000, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_1", .id = DSC_1, .base = 0x80400, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_2", .id = DSC_2, .base = 0x80800, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, { .name = "dsc_3", .id = DSC_3, .base = 0x80c00, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, }; @@ -293,7 +274,6 @@ static const struct dpu_intf_cfg sm8250_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x6a000, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -302,7 +282,6 @@ static const struct dpu_intf_cfg sm8250_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2c0, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -312,7 +291,6 @@ static const struct dpu_intf_cfg sm8250_intf[] = { }, { .name = "intf_2", .id = INTF_2, .base = 0x6b000, .len = 0x2c0, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -322,7 +300,6 @@ static const struct dpu_intf_cfg sm8250_intf[] = { }, { .name = "intf_3", .id = INTF_3, .base = 0x6b800, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -335,7 +312,7 @@ static const struct dpu_wb_cfg sm8250_wb[] = { { .name = "wb_2", .id = WB_2, .base = 0x65000, .len = 0x2c8, - .features = WB_SM8250_MASK, + .features = WB_SDM845_MASK, .format_list = wb2_formats_rgb_yuv, .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .clk_ctrl = DPU_CLK_CTRL_WB2, @@ -384,7 +361,7 @@ const struct dpu_mdss_cfg dpu_sm8250_cfg = { .mdss_ver = &sm8250_mdss_ver, .caps = &sm8250_dpu_caps, .mdp = &sm8250_mdp, - .cdm = &sc7280_cdm, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sm8250_ctl), .ctl = sm8250_ctl, .sspp_count = ARRAY_SIZE(sm8250_sspp), 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 7382ebb6e5b2..c990ba3b5db0 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 @@ -32,17 +32,14 @@ static const struct dpu_ctl_cfg sc7180_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1dc, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x1200, .len = 0x1dc, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x1400, .len = 0x1dc, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, }; @@ -51,7 +48,7 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f8, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -59,7 +56,7 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f8, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -67,7 +64,7 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f8, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -75,7 +72,7 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x1f8, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, @@ -87,7 +84,7 @@ static const struct dpu_lm_cfg sc7180_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sc7180_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -95,7 +92,7 @@ static const struct dpu_lm_cfg sc7180_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sc7180_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -106,7 +103,6 @@ static const struct dpu_dspp_cfg sc7180_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -115,14 +111,12 @@ static const struct dpu_pingpong_cfg sc7180_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), @@ -133,7 +127,6 @@ static const struct dpu_intf_cfg sc7180_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x6a000, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -142,7 +135,6 @@ static const struct dpu_intf_cfg sc7180_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2c0, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -156,9 +148,9 @@ static const struct dpu_wb_cfg sc7180_wb[] = { { .name = "wb_2", .id = WB_2, .base = 0x65000, .len = 0x2c8, - .features = WB_SM8250_MASK, - .format_list = wb2_formats_rgb, - .num_formats = ARRAY_SIZE(wb2_formats_rgb), + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .clk_ctrl = DPU_CLK_CTRL_WB2, .xin_id = 6, .vbif_idx = VBIF_RT, @@ -204,6 +196,7 @@ const struct dpu_mdss_cfg dpu_sc7180_cfg = { .mdss_ver = &sc7180_mdss_ver, .caps = &sc7180_dpu_caps, .mdp = &sc7180_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sc7180_ctl), .ctl = sc7180_ctl, .sspp_count = ARRAY_SIZE(sc7180_sspp), 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 43f64a005f5a..343ff5482382 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 @@ -29,7 +29,6 @@ static const struct dpu_ctl_cfg sm6115_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1dc, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, }; @@ -38,7 +37,7 @@ static const struct dpu_sspp_cfg sm6115_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f8, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -46,7 +45,7 @@ static const struct dpu_sspp_cfg sm6115_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f8, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -58,7 +57,6 @@ static const struct dpu_lm_cfg sm6115_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_QCM2290_MASK, .sblk = &qcm2290_lm_sblk, .pingpong = PINGPONG_0, .dspp = DSPP_0, @@ -69,7 +67,6 @@ static const struct dpu_dspp_cfg sm6115_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -78,7 +75,6 @@ static const struct dpu_pingpong_cfg sm6115_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), @@ -89,7 +85,6 @@ static const struct dpu_intf_cfg sm6115_intf[] = { { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2c0, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, 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 0502cee2f116..093d16bdc450 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 @@ -35,22 +35,18 @@ static const struct dpu_ctl_cfg sm6350_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1dc, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x1200, .len = 0x1dc, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x1400, .len = 0x1dc, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x1600, .len = 0x1dc, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, }; @@ -59,7 +55,7 @@ static const struct dpu_sspp_cfg sm6350_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f8, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -67,7 +63,7 @@ static const struct dpu_sspp_cfg sm6350_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f8, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -75,7 +71,7 @@ static const struct dpu_sspp_cfg sm6350_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x1f8, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -83,7 +79,7 @@ static const struct dpu_sspp_cfg sm6350_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x1f8, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, @@ -95,7 +91,7 @@ static const struct dpu_lm_cfg sm6350_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sc7180_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -103,7 +99,7 @@ static const struct dpu_lm_cfg sm6350_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sc7180_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -115,7 +111,6 @@ static const struct dpu_dspp_cfg sm6350_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -124,14 +119,12 @@ static struct dpu_pingpong_cfg sm6350_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x70800, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), @@ -142,7 +135,6 @@ static const struct dpu_dsc_cfg sm6350_dsc[] = { { .name = "dsc_0", .id = DSC_0, .base = 0x80000, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, }; @@ -150,9 +142,9 @@ static const struct dpu_wb_cfg sm6350_wb[] = { { .name = "wb_2", .id = WB_2, .base = 0x65000, .len = 0x2c8, - .features = WB_SM8250_MASK, - .format_list = wb2_formats_rgb, - .num_formats = ARRAY_SIZE(wb2_formats_rgb), + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .clk_ctrl = DPU_CLK_CTRL_WB2, .xin_id = 6, .vbif_idx = VBIF_RT, @@ -165,7 +157,6 @@ static const struct dpu_intf_cfg sm6350_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x6a000, .len = 0x280, - .features = INTF_SC7180_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 35, @@ -174,7 +165,6 @@ static const struct dpu_intf_cfg sm6350_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2c0, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 35, @@ -222,6 +212,7 @@ const struct dpu_mdss_cfg dpu_sm6350_cfg = { .mdss_ver = &sm6350_mdss_ver, .caps = &sm6350_dpu_caps, .mdp = &sm6350_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sm6350_ctl), .ctl = sm6350_ctl, .sspp_count = ARRAY_SIZE(sm6350_sspp), 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 3cbb2fe8aba2..47053bf9b0a2 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 @@ -29,7 +29,6 @@ static const struct dpu_ctl_cfg qcm2290_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1dc, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, }; @@ -46,7 +45,7 @@ static const struct dpu_sspp_cfg qcm2290_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f8, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -58,7 +57,6 @@ static const struct dpu_lm_cfg qcm2290_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_QCM2290_MASK, .sblk = &qcm2290_lm_sblk, .pingpong = PINGPONG_0, .dspp = DSPP_0, @@ -69,7 +67,6 @@ static const struct dpu_dspp_cfg qcm2290_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -78,7 +75,6 @@ static const struct dpu_pingpong_cfg qcm2290_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), @@ -89,7 +85,6 @@ static const struct dpu_intf_cfg qcm2290_intf[] = { { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2c0, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, 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 a06c8634d2d7..98190ee7ec7a 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 @@ -30,7 +30,6 @@ static const struct dpu_ctl_cfg sm6375_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x1000, .len = 0x1dc, - .features = BIT(DPU_CTL_ACTIVE_CFG), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, }; @@ -39,7 +38,7 @@ static const struct dpu_sspp_cfg sm6375_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x1f8, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_NO_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -47,7 +46,7 @@ static const struct dpu_sspp_cfg sm6375_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x1f8, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_NO_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -59,7 +58,6 @@ static const struct dpu_lm_cfg sm6375_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_QCM2290_MASK, .sblk = &qcm2290_lm_sblk, .lm_pair = 0, .pingpong = PINGPONG_0, @@ -71,7 +69,6 @@ static const struct dpu_dspp_cfg sm6375_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -80,7 +77,6 @@ static const struct dpu_pingpong_cfg sm6375_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x70000, .len = 0xd4, - .features = PINGPONG_SM8150_MASK, .sblk = &sdm845_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), @@ -91,7 +87,6 @@ static const struct dpu_dsc_cfg sm6375_dsc[] = { { .name = "dsc_0", .id = DSC_0, .base = 0x80000, .len = 0x140, - .features = BIT(DPU_DSC_OUTPUT_CTRL), }, }; @@ -99,7 +94,6 @@ static const struct dpu_intf_cfg sm6375_intf[] = { { .name = "intf_1", .id = INTF_1, .base = 0x6a800, .len = 0x2c0, - .features = INTF_SC7180_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, 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 aced16e350da..85aae40c210f 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 @@ -35,37 +35,30 @@ static const struct dpu_mdp_cfg sm8350_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8350_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x1e8, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x1e8, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x17000, .len = 0x1e8, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x18000, .len = 0x1e8, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x19000, .len = 0x1e8, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a000, .len = 0x1e8, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -142,7 +135,7 @@ static const struct dpu_lm_cfg sm8350_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -150,7 +143,7 @@ static const struct dpu_lm_cfg sm8350_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -158,28 +151,30 @@ static const struct dpu_lm_cfg sm8350_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, + .dspp = DSPP_2, }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, + .dspp = DSPP_3, }, { .name = "lm_4", .id = LM_4, .base = 0x48000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_5, .pingpong = PINGPONG_4, }, { .name = "lm_5", .id = LM_5, .base = 0x49000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_4, .pingpong = PINGPONG_5, @@ -190,22 +185,18 @@ static const struct dpu_dspp_cfg sm8350_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_2", .id = DSPP_2, .base = 0x58000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_3", .id = DSPP_3, .base = 0x5a000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -214,42 +205,36 @@ static const struct dpu_pingpong_cfg sm8350_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x69000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x6d000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x6e000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), @@ -278,22 +263,20 @@ static const struct dpu_dsc_cfg sm8350_dsc[] = { { .name = "dce_0_0", .id = DSC_0, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_0, }, { .name = "dce_0_1", .id = DSC_1, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_1, }, { .name = "dce_1_0", .id = DSC_2, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_0, }, { .name = "dce_1_1", .id = DSC_3, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_1, }, }; @@ -302,9 +285,9 @@ 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_rgb, - .num_formats = ARRAY_SIZE(wb2_formats_rgb), + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .clk_ctrl = DPU_CLK_CTRL_WB2, .xin_id = 6, .vbif_idx = VBIF_RT, @@ -317,7 +300,6 @@ static const struct dpu_intf_cfg sm8350_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x34000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -326,7 +308,6 @@ static const struct dpu_intf_cfg sm8350_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x2c4, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -336,7 +317,6 @@ static const struct dpu_intf_cfg sm8350_intf[] = { }, { .name = "intf_2", .id = INTF_2, .base = 0x36000, .len = 0x2c4, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -346,7 +326,6 @@ static const struct dpu_intf_cfg sm8350_intf[] = { }, { .name = "intf_3", .id = INTF_3, .base = 0x37000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -394,6 +373,7 @@ const struct dpu_mdss_cfg dpu_sm8350_cfg = { .mdss_ver = &sm8350_mdss_ver, .caps = &sm8350_dpu_caps, .mdp = &sm8350_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sm8350_ctl), .ctl = sm8350_ctl, .sspp_count = ARRAY_SIZE(sm8350_sspp), 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 2f153e0b5c6a..8f978b9c3452 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 @@ -32,22 +32,18 @@ static const struct dpu_ctl_cfg sc7280_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x1e8, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x1e8, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x17000, .len = 0x1e8, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x18000, .len = 0x1e8, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, }; @@ -92,21 +88,21 @@ static const struct dpu_lm_cfg sc7280_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sc7180_lm_sblk, .pingpong = PINGPONG_0, .dspp = DSPP_0, }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sc7180_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sc7180_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, @@ -117,7 +113,6 @@ static const struct dpu_dspp_cfg sc7280_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -126,28 +121,24 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x69000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = 0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), @@ -159,7 +150,7 @@ static const struct dpu_dsc_cfg sc7280_dsc[] = { { .name = "dce_0_0", .id = DSC_0, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_0, }, }; @@ -168,7 +159,7 @@ static const struct dpu_wb_cfg sc7280_wb[] = { { .name = "wb_2", .id = WB_2, .base = 0x65000, .len = 0x2c8, - .features = WB_SM8250_MASK, + .features = WB_SDM845_MASK, .format_list = wb2_formats_rgb_yuv, .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .clk_ctrl = DPU_CLK_CTRL_WB2, @@ -183,7 +174,6 @@ static const struct dpu_intf_cfg sc7280_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x34000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -192,7 +182,6 @@ static const struct dpu_intf_cfg sc7280_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x2c4, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -202,7 +191,6 @@ static const struct dpu_intf_cfg sc7280_intf[] = { }, { .name = "intf_5", .id = INTF_5, .base = 0x39000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -248,7 +236,7 @@ const struct dpu_mdss_cfg dpu_sc7280_cfg = { .mdss_ver = &sc7280_mdss_ver, .caps = &sc7280_dpu_caps, .mdp = &sc7280_mdp, - .cdm = &sc7280_cdm, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sc7280_ctl), .ctl = sc7280_ctl, .sspp_count = ARRAY_SIZE(sc7280_sspp), 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 0d143e390eca..303d33dc7783 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 @@ -21,7 +21,6 @@ static const struct dpu_caps sc8280xp_dpu_caps = { static const struct dpu_mdp_cfg sc8280xp_mdp = { .name = "top_0", .base = 0x0, .len = 0x494, - .features = BIT(DPU_MDP_PERIPH_0_REMOVED), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, @@ -35,37 +34,30 @@ static const struct dpu_mdp_cfg sc8280xp_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sc8280xp_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x17000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x18000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x19000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -74,7 +66,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x2ac, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 0, .type = SSPP_TYPE_VIG, @@ -82,7 +74,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x2ac, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 4, .type = SSPP_TYPE_VIG, @@ -90,7 +82,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x2ac, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 8, .type = SSPP_TYPE_VIG, @@ -98,7 +90,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x2ac, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_0, .xin_id = 12, .type = SSPP_TYPE_VIG, @@ -106,7 +98,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x2ac, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, @@ -114,7 +106,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x2ac, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, @@ -122,7 +114,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x2ac, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, @@ -130,7 +122,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { }, { .name = "sspp_11", .id = SSPP_DMA3, .base = 0x2a000, .len = 0x2ac, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 13, .type = SSPP_TYPE_DMA, @@ -142,7 +134,7 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -150,7 +142,7 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -158,7 +150,7 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, @@ -166,7 +158,7 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = { }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, @@ -174,14 +166,14 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = { }, { .name = "lm_4", .id = LM_4, .base = 0x48000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_5, .pingpong = PINGPONG_4, }, { .name = "lm_5", .id = LM_5, .base = 0x49000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_4, .pingpong = PINGPONG_5, @@ -192,22 +184,18 @@ static const struct dpu_dspp_cfg sc8280xp_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_2", .id = DSPP_2, .base = 0x58000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_3", .id = DSPP_3, .base = 0x5a000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -216,42 +204,36 @@ static const struct dpu_pingpong_cfg sc8280xp_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x69000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x6d000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x6e000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), @@ -280,32 +262,28 @@ static const struct dpu_dsc_cfg sc8280xp_dsc[] = { { .name = "dce_0_0", .id = DSC_0, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_0, }, { .name = "dce_0_1", .id = DSC_1, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_1, }, { .name = "dce_1_0", .id = DSC_2, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_0, }, { .name = "dce_1_1", .id = DSC_3, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_1, }, { .name = "dce_2_0", .id = DSC_4, .base = 0x82000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_0, }, { .name = "dce_2_1", .id = DSC_5, .base = 0x82000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_1, }, }; @@ -315,7 +293,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x34000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -324,7 +301,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -334,7 +310,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { }, { .name = "intf_2", .id = INTF_2, .base = 0x36000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -344,7 +319,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { }, { .name = "intf_3", .id = INTF_3, .base = 0x37000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_NONE, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -353,7 +327,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { }, { .name = "intf_4", .id = INTF_4, .base = 0x38000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -362,7 +335,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { }, { .name = "intf_5", .id = INTF_5, .base = 0x39000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_3, .prog_fetch_lines_worst_case = 24, @@ -371,7 +343,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { }, { .name = "intf_6", .id = INTF_6, .base = 0x3a000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_2, .prog_fetch_lines_worst_case = 24, @@ -380,7 +351,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { }, { .name = "intf_7", .id = INTF_7, .base = 0x3b000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_NONE, .controller_id = MSM_DP_CONTROLLER_2, .prog_fetch_lines_worst_case = 24, @@ -389,7 +359,6 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = { }, { .name = "intf_8", .id = INTF_8, .base = 0x3c000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_NONE, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -435,6 +404,7 @@ const struct dpu_mdss_cfg dpu_sc8280xp_cfg = { .mdss_ver = &sc8280xp_mdss_ver, .caps = &sc8280xp_dpu_caps, .mdp = &sc8280xp_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sc8280xp_ctl), .ctl = sc8280xp_ctl, .sspp_count = ARRAY_SIZE(sc8280xp_sspp), 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 a1779c5597ae..b09a6af4c474 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 @@ -21,7 +21,6 @@ static const struct dpu_caps sm8450_dpu_caps = { static const struct dpu_mdp_cfg sm8450_mdp = { .name = "top_0", .base = 0x0, .len = 0x494, - .features = BIT(DPU_MDP_PERIPH_0_REMOVED), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, @@ -36,37 +35,30 @@ static const struct dpu_mdp_cfg sm8450_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8450_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x17000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x18000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x19000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -143,7 +135,7 @@ static const struct dpu_lm_cfg sm8450_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -151,7 +143,7 @@ static const struct dpu_lm_cfg sm8450_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -159,7 +151,7 @@ static const struct dpu_lm_cfg sm8450_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, @@ -167,7 +159,7 @@ static const struct dpu_lm_cfg sm8450_lm[] = { }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, @@ -175,14 +167,14 @@ static const struct dpu_lm_cfg sm8450_lm[] = { }, { .name = "lm_4", .id = LM_4, .base = 0x48000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_5, .pingpong = PINGPONG_4, }, { .name = "lm_5", .id = LM_5, .base = 0x49000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_4, .pingpong = PINGPONG_5, @@ -193,22 +185,18 @@ static const struct dpu_dspp_cfg sm8450_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_2", .id = DSPP_2, .base = 0x58000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_3", .id = DSPP_3, .base = 0x5a000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -217,55 +205,47 @@ static const struct dpu_pingpong_cfg sm8450_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x69000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x6d000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x6e000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), }, { - .name = "pingpong_6", .id = PINGPONG_6, + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, .base = 0x65800, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, }, { - .name = "pingpong_7", .id = PINGPONG_7, + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, .base = 0x65c00, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, }, @@ -296,22 +276,20 @@ static const struct dpu_dsc_cfg sm8450_dsc[] = { { .name = "dce_0_0", .id = DSC_0, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_0, }, { .name = "dce_0_1", .id = DSC_1, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_1, }, { .name = "dce_1_0", .id = DSC_2, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_0, }, { .name = "dce_1_1", .id = DSC_3, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_1, }, }; @@ -320,9 +298,9 @@ 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_rgb, - .num_formats = ARRAY_SIZE(wb2_formats_rgb), + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .clk_ctrl = DPU_CLK_CTRL_WB2, .xin_id = 6, .vbif_idx = VBIF_RT, @@ -335,7 +313,6 @@ static const struct dpu_intf_cfg sm8450_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x34000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -344,7 +321,6 @@ static const struct dpu_intf_cfg sm8450_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -354,7 +330,6 @@ static const struct dpu_intf_cfg sm8450_intf[] = { }, { .name = "intf_2", .id = INTF_2, .base = 0x36000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -364,7 +339,6 @@ static const struct dpu_intf_cfg sm8450_intf[] = { }, { .name = "intf_3", .id = INTF_3, .base = 0x37000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -412,6 +386,7 @@ const struct dpu_mdss_cfg dpu_sm8450_cfg = { .mdss_ver = &sm8450_mdss_ver, .caps = &sm8450_dpu_caps, .mdp = &sm8450_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sm8450_ctl), .ctl = sm8450_ctl, .sspp_count = ARRAY_SIZE(sm8450_sspp), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h index 907b4d7ceb47..0f7b4a224e4c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h @@ -20,7 +20,6 @@ static const struct dpu_caps sa8775p_dpu_caps = { static const struct dpu_mdp_cfg sa8775p_mdp = { .name = "top_0", .base = 0x0, .len = 0x494, - .features = BIT(DPU_MDP_PERIPH_0_REMOVED), .clk_ctrls = { [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, @@ -35,37 +34,30 @@ static const struct dpu_mdp_cfg sa8775p_mdp = { }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sa8775p_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x204, - .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x17000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x18000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x19000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a000, .len = 0x204, - .features = CTL_SC7280_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -142,7 +134,7 @@ static const struct dpu_lm_cfg sa8775p_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -150,7 +142,7 @@ static const struct dpu_lm_cfg sa8775p_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -158,7 +150,7 @@ static const struct dpu_lm_cfg sa8775p_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, @@ -166,7 +158,7 @@ static const struct dpu_lm_cfg sa8775p_lm[] = { }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, @@ -174,14 +166,14 @@ static const struct dpu_lm_cfg sa8775p_lm[] = { }, { .name = "lm_4", .id = LM_4, .base = 0x48000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_5, .pingpong = PINGPONG_4, }, { .name = "lm_5", .id = LM_5, .base = 0x49000, .len = 0x400, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_4, .pingpong = PINGPONG_5, @@ -192,22 +184,18 @@ static const struct dpu_dspp_cfg sa8775p_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_2", .id = DSPP_2, .base = 0x58000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_3", .id = DSPP_3, .base = 0x5a000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -216,55 +204,47 @@ static const struct dpu_pingpong_cfg sa8775p_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x69000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x6d000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x6e000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), }, { - .name = "pingpong_6", .id = PINGPONG_6, + .name = "pingpong_6", .id = PINGPONG_CWB_0, .base = 0x65800, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, }, { - .name = "pingpong_7", .id = PINGPONG_7, + .name = "pingpong_7", .id = PINGPONG_CWB_1, .base = 0x65c00, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, }, @@ -295,32 +275,28 @@ static const struct dpu_dsc_cfg sa8775p_dsc[] = { { .name = "dce_0_0", .id = DSC_0, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_0, }, { .name = "dce_0_1", .id = DSC_1, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_1, }, { .name = "dce_1_0", .id = DSC_2, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_0, }, { .name = "dce_1_1", .id = DSC_3, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_1, }, { .name = "dce_2_0", .id = DSC_4, .base = 0x82000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_0, }, { .name = "dce_2_1", .id = DSC_5, .base = 0x82000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_1, }, }; @@ -329,7 +305,7 @@ static const struct dpu_wb_cfg sa8775p_wb[] = { { .name = "wb_2", .id = WB_2, .base = 0x65000, .len = 0x2c8, - .features = WB_SM8250_MASK, + .features = WB_SDM845_MASK, .format_list = wb2_formats_rgb_yuv, .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .clk_ctrl = DPU_CLK_CTRL_WB2, @@ -345,7 +321,6 @@ static const struct dpu_intf_cfg sa8775p_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x34000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -354,7 +329,6 @@ static const struct dpu_intf_cfg sa8775p_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -364,7 +338,6 @@ static const struct dpu_intf_cfg sa8775p_intf[] = { }, { .name = "intf_2", .id = INTF_2, .base = 0x36000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -374,7 +347,6 @@ static const struct dpu_intf_cfg sa8775p_intf[] = { }, { .name = "intf_3", .id = INTF_3, .base = 0x37000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_NONE, .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ .prog_fetch_lines_worst_case = 24, @@ -383,7 +355,6 @@ static const struct dpu_intf_cfg sa8775p_intf[] = { }, { .name = "intf_4", .id = INTF_4, .base = 0x38000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -392,7 +363,6 @@ static const struct dpu_intf_cfg sa8775p_intf[] = { }, { .name = "intf_6", .id = INTF_6, .base = 0x3A000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_NONE, .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ .prog_fetch_lines_worst_case = 24, @@ -401,7 +371,6 @@ static const struct dpu_intf_cfg sa8775p_intf[] = { }, { .name = "intf_7", .id = INTF_7, .base = 0x3b000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_NONE, .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ .prog_fetch_lines_worst_case = 24, @@ -410,7 +379,6 @@ static const struct dpu_intf_cfg sa8775p_intf[] = { }, { .name = "intf_8", .id = INTF_8, .base = 0x3c000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_NONE, .controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_4 for DP MST */ .prog_fetch_lines_worst_case = 24, @@ -458,7 +426,7 @@ const struct dpu_mdss_cfg dpu_sa8775p_cfg = { .mdss_ver = &sa8775p_mdss_ver, .caps = &sa8775p_dpu_caps, .mdp = &sa8775p_mdp, - .cdm = &sc7280_cdm, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sa8775p_ctl), .ctl = sa8775p_ctl, .sspp_count = ARRAY_SIZE(sa8775p_sspp), 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 ad48defa154f..465b6460f875 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 @@ -21,43 +21,35 @@ static const struct dpu_caps sm8550_dpu_caps = { static const struct dpu_mdp_cfg sm8550_mdp = { .name = "top_0", .base = 0, .len = 0x494, - .features = BIT(DPU_MDP_PERIPH_0_REMOVED), .clk_ctrls = { [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg sm8550_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x290, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x290, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x17000, .len = 0x290, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x18000, .len = 0x290, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x19000, .len = 0x290, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a000, .len = 0x290, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -66,70 +58,70 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { { .name = "sspp_0", .id = SSPP_VIG0, .base = 0x4000, .len = 0x344, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_2, .xin_id = 0, .type = SSPP_TYPE_VIG, }, { .name = "sspp_1", .id = SSPP_VIG1, .base = 0x6000, .len = 0x344, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_2, .xin_id = 4, .type = SSPP_TYPE_VIG, }, { .name = "sspp_2", .id = SSPP_VIG2, .base = 0x8000, .len = 0x344, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_2, .xin_id = 8, .type = SSPP_TYPE_VIG, }, { .name = "sspp_3", .id = SSPP_VIG3, .base = 0xa000, .len = 0x344, - .features = VIG_SDM845_MASK, + .features = VIG_SDM845_MASK_SDMA, .sblk = &dpu_vig_sblk_qseed3_3_2, .xin_id = 12, .type = SSPP_TYPE_VIG, }, { .name = "sspp_8", .id = SSPP_DMA0, .base = 0x24000, .len = 0x344, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 1, .type = SSPP_TYPE_DMA, }, { .name = "sspp_9", .id = SSPP_DMA1, .base = 0x26000, .len = 0x344, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 5, .type = SSPP_TYPE_DMA, }, { .name = "sspp_10", .id = SSPP_DMA2, .base = 0x28000, .len = 0x344, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 9, .type = SSPP_TYPE_DMA, }, { .name = "sspp_11", .id = SSPP_DMA3, .base = 0x2a000, .len = 0x344, - .features = DMA_SDM845_MASK, + .features = DMA_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 13, .type = SSPP_TYPE_DMA, }, { .name = "sspp_12", .id = SSPP_DMA4, .base = 0x2c000, .len = 0x344, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 14, .type = SSPP_TYPE_DMA, }, { .name = "sspp_13", .id = SSPP_DMA5, .base = 0x2e000, .len = 0x344, - .features = DMA_CURSOR_SDM845_MASK, + .features = DMA_CURSOR_SDM845_MASK_SDMA, .sblk = &dpu_dma_sblk, .xin_id = 15, .type = SSPP_TYPE_DMA, @@ -140,7 +132,7 @@ static const struct dpu_lm_cfg sm8550_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -148,7 +140,7 @@ static const struct dpu_lm_cfg sm8550_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -156,28 +148,30 @@ static const struct dpu_lm_cfg sm8550_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, + .dspp = DSPP_2, }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, + .dspp = DSPP_3, }, { .name = "lm_4", .id = LM_4, .base = 0x48000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_5, .pingpong = PINGPONG_4, }, { .name = "lm_5", .id = LM_5, .base = 0x49000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_4, .pingpong = PINGPONG_5, @@ -188,22 +182,18 @@ static const struct dpu_dspp_cfg sm8550_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_2", .id = DSPP_2, .base = 0x58000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_3", .id = DSPP_3, .base = 0x5a000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -211,55 +201,47 @@ static const struct dpu_pingpong_cfg sm8550_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x69000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x6d000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x6e000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), }, { - .name = "pingpong_6", .id = PINGPONG_6, + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, .base = 0x66000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, }, { - .name = "pingpong_7", .id = PINGPONG_7, + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, .base = 0x66400, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, }, @@ -290,22 +272,20 @@ static const struct dpu_dsc_cfg sm8550_dsc[] = { { .name = "dce_0_0", .id = DSC_0, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_0, }, { .name = "dce_0_1", .id = DSC_1, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_1, }, { .name = "dce_1_0", .id = DSC_2, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_0, }, { .name = "dce_1_1", .id = DSC_3, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_1, }, }; @@ -314,9 +294,9 @@ 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_rgb, - .num_formats = ARRAY_SIZE(wb2_formats_rgb), + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .xin_id = 6, .vbif_idx = VBIF_RT, .maxlinewidth = 4096, @@ -328,7 +308,6 @@ static const struct dpu_intf_cfg sm8550_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x34000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -337,7 +316,6 @@ static const struct dpu_intf_cfg sm8550_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -347,7 +325,6 @@ static const struct dpu_intf_cfg sm8550_intf[] = { }, { .name = "intf_2", .id = INTF_2, .base = 0x36000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -357,7 +334,6 @@ static const struct dpu_intf_cfg sm8550_intf[] = { }, { .name = "intf_3", .id = INTF_3, .base = 0x37000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -405,6 +381,7 @@ const struct dpu_mdss_cfg dpu_sm8550_cfg = { .mdss_ver = &sm8550_mdss_ver, .caps = &sm8550_dpu_caps, .mdp = &sm8550_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(sm8550_ctl), .ctl = sm8550_ctl, .sspp_count = ARRAY_SIZE(sm8550_sspp), diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h new file mode 100644 index 000000000000..6caa7d40f368 --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h @@ -0,0 +1,408 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. + */ + +#ifndef _DPU_9_1_SAR2130P_H +#define _DPU_9_1_SAR2130P_H + +static const struct dpu_caps sar2130p_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0xb, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 5120, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, +}; + +static const struct dpu_mdp_cfg sar2130p_mdp = { + .name = "top_0", + .base = 0, .len = 0x494, + .clk_ctrls = { + [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, + }, +}; + +static const struct dpu_ctl_cfg sar2130p_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x15000, .len = 0x290, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, { + .name = "ctl_1", .id = CTL_1, + .base = 0x16000, .len = 0x290, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, { + .name = "ctl_2", .id = CTL_2, + .base = 0x17000, .len = 0x290, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, { + .name = "ctl_3", .id = CTL_3, + .base = 0x18000, .len = 0x290, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, { + .name = "ctl_4", .id = CTL_4, + .base = 0x19000, .len = 0x290, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, { + .name = "ctl_5", .id = CTL_5, + .base = 0x1a000, .len = 0x290, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), + }, +}; + +static const struct dpu_sspp_cfg sar2130p_sspp[] = { + { + .name = "sspp_0", .id = SSPP_VIG0, + .base = 0x4000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_2, + .xin_id = 0, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_1", .id = SSPP_VIG1, + .base = 0x6000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_2, + .xin_id = 4, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_2", .id = SSPP_VIG2, + .base = 0x8000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_2, + .xin_id = 8, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_3", .id = SSPP_VIG3, + .base = 0xa000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_2, + .xin_id = 12, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_8", .id = SSPP_DMA0, + .base = 0x24000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 1, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_9", .id = SSPP_DMA1, + .base = 0x26000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 5, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_10", .id = SSPP_DMA2, + .base = 0x28000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 9, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_11", .id = SSPP_DMA3, + .base = 0x2a000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 13, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_12", .id = SSPP_DMA4, + .base = 0x2c000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 14, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_13", .id = SSPP_DMA5, + .base = 0x2e000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 15, + .type = SSPP_TYPE_DMA, + }, +}; + +static const struct dpu_lm_cfg sar2130p_lm[] = { + { + .name = "lm_0", .id = LM_0, + .base = 0x44000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_1, + .pingpong = PINGPONG_0, + .dspp = DSPP_0, + }, { + .name = "lm_1", .id = LM_1, + .base = 0x45000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_0, + .pingpong = PINGPONG_1, + .dspp = DSPP_1, + }, { + .name = "lm_2", .id = LM_2, + .base = 0x46000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_3, + .pingpong = PINGPONG_2, + .dspp = DSPP_2, + }, { + .name = "lm_3", .id = LM_3, + .base = 0x47000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_2, + .pingpong = PINGPONG_3, + .dspp = DSPP_3, + }, { + .name = "lm_4", .id = LM_4, + .base = 0x48000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_5, + .pingpong = PINGPONG_4, + }, { + .name = "lm_5", .id = LM_5, + .base = 0x49000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_4, + .pingpong = PINGPONG_5, + }, +}; + +static const struct dpu_dspp_cfg sar2130p_dspp[] = { + { + .name = "dspp_0", .id = DSPP_0, + .base = 0x54000, .len = 0x1800, + .sblk = &sdm845_dspp_sblk, + }, { + .name = "dspp_1", .id = DSPP_1, + .base = 0x56000, .len = 0x1800, + .sblk = &sdm845_dspp_sblk, + }, { + .name = "dspp_2", .id = DSPP_2, + .base = 0x58000, .len = 0x1800, + .sblk = &sdm845_dspp_sblk, + }, { + .name = "dspp_3", .id = DSPP_3, + .base = 0x5a000, .len = 0x1800, + .sblk = &sdm845_dspp_sblk, + }, +}; +static const struct dpu_pingpong_cfg sar2130p_pp[] = { + { + .name = "pingpong_0", .id = PINGPONG_0, + .base = 0x69000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + }, { + .name = "pingpong_1", .id = PINGPONG_1, + .base = 0x6a000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), + }, { + .name = "pingpong_2", .id = PINGPONG_2, + .base = 0x6b000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + }, { + .name = "pingpong_3", .id = PINGPONG_3, + .base = 0x6c000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), + }, { + .name = "pingpong_4", .id = PINGPONG_4, + .base = 0x6d000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), + }, { + .name = "pingpong_5", .id = PINGPONG_5, + .base = 0x6e000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), + }, { + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, + .base = 0x66000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + }, { + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, + .base = 0x66400, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + }, +}; + +static const struct dpu_merge_3d_cfg sar2130p_merge_3d[] = { + { + .name = "merge_3d_0", .id = MERGE_3D_0, + .base = 0x4e000, .len = 0x8, + }, { + .name = "merge_3d_1", .id = MERGE_3D_1, + .base = 0x4f000, .len = 0x8, + }, { + .name = "merge_3d_2", .id = MERGE_3D_2, + .base = 0x50000, .len = 0x8, + }, { + .name = "merge_3d_3", .id = MERGE_3D_3, + .base = 0x66700, .len = 0x8, + }, +}; + +/* + * NOTE: Each display compression engine (DCE) contains dual hard + * slice DSC encoders so both share same base address but with + * its own different sub block address. + */ +static const struct dpu_dsc_cfg sar2130p_dsc[] = { + { + .name = "dce_0_0", .id = DSC_0, + .base = 0x80000, .len = 0x4, + .sblk = &dsc_sblk_0, + }, { + .name = "dce_0_1", .id = DSC_1, + .base = 0x80000, .len = 0x4, + .sblk = &dsc_sblk_1, + }, { + .name = "dce_1_0", .id = DSC_2, + .base = 0x81000, .len = 0x4, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &dsc_sblk_0, + }, { + .name = "dce_1_1", .id = DSC_3, + .base = 0x81000, .len = 0x4, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &dsc_sblk_1, + }, +}; + +static const struct dpu_wb_cfg sar2130p_wb[] = { + { + .name = "wb_2", .id = WB_2, + .base = 0x65000, .len = 0x2c8, + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), + .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 sar2130p_intf[] = { + { + .name = "intf_0", .id = INTF_0, + .base = 0x34000, .len = 0x280, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .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), + }, { + .name = "intf_1", .id = INTF_1, + .base = 0x35000, .len = 0x300, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_0, + .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 = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2), + }, { + .name = "intf_2", .id = INTF_2, + .base = 0x36000, .len = 0x300, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_1, + .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 = DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2), + }, { + .name = "intf_3", .id = INTF_3, + .base = 0x37000, .len = 0x280, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, + .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), + }, +}; + +static const struct dpu_perf_cfg sar2130p_perf_data = { + .max_bw_low = 13600000, + .max_bw_high = 18200000, + .min_core_ib = 2500000, + .min_llcc_ib = 0, + .min_dram_ib = 800000, + .min_prefill_lines = 35, + /* FIXME: lut tables */ + .danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0}, + .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(sc7180_qos_linear), + .entries = sc7180_qos_linear + }, + {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), + .entries = sc7180_qos_macrotile + }, + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), + .entries = sc7180_qos_nrt + }, + /* TODO: macrotile-qseed is different from macrotile */ + }, + .cdp_cfg = { + {.rd_enable = 0, .wr_enable = 0}, + {.rd_enable = 0, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; + +static const struct dpu_mdss_version sar2130p_mdss_ver = { + .core_major_ver = 9, + .core_minor_ver = 1, +}; + +const struct dpu_mdss_cfg dpu_sar2130p_cfg = { + .mdss_ver = &sar2130p_mdss_ver, + .caps = &sar2130p_dpu_caps, + .mdp = &sar2130p_mdp, + .cdm = &dpu_cdm_5_x, + .ctl_count = ARRAY_SIZE(sar2130p_ctl), + .ctl = sar2130p_ctl, + .sspp_count = ARRAY_SIZE(sar2130p_sspp), + .sspp = sar2130p_sspp, + .mixer_count = ARRAY_SIZE(sar2130p_lm), + .mixer = sar2130p_lm, + .dspp_count = ARRAY_SIZE(sar2130p_dspp), + .dspp = sar2130p_dspp, + .pingpong_count = ARRAY_SIZE(sar2130p_pp), + .pingpong = sar2130p_pp, + .dsc_count = ARRAY_SIZE(sar2130p_dsc), + .dsc = sar2130p_dsc, + .merge_3d_count = ARRAY_SIZE(sar2130p_merge_3d), + .merge_3d = sar2130p_merge_3d, + .wb_count = ARRAY_SIZE(sar2130p_wb), + .wb = sar2130p_wb, + .intf_count = ARRAY_SIZE(sar2130p_intf), + .intf = sar2130p_intf, + .vbif_count = ARRAY_SIZE(sm8550_vbif), + .vbif = sm8550_vbif, + .perf = &sar2130p_perf_data, +}; + +#endif diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h index a3e60ac70689..7243eebb85f3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h @@ -20,43 +20,35 @@ static const struct dpu_caps x1e80100_dpu_caps = { static const struct dpu_mdp_cfg x1e80100_mdp = { .name = "top_0", .base = 0, .len = 0x494, - .features = BIT(DPU_MDP_PERIPH_0_REMOVED), .clk_ctrls = { [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, }, }; -/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */ static const struct dpu_ctl_cfg x1e80100_ctl[] = { { .name = "ctl_0", .id = CTL_0, .base = 0x15000, .len = 0x290, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), }, { .name = "ctl_1", .id = CTL_1, .base = 0x16000, .len = 0x290, - .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), }, { .name = "ctl_2", .id = CTL_2, .base = 0x17000, .len = 0x290, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), }, { .name = "ctl_3", .id = CTL_3, .base = 0x18000, .len = 0x290, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), }, { .name = "ctl_4", .id = CTL_4, .base = 0x19000, .len = 0x290, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), }, { .name = "ctl_5", .id = CTL_5, .base = 0x1a000, .len = 0x290, - .features = CTL_SM8550_MASK, .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), }, }; @@ -139,7 +131,7 @@ static const struct dpu_lm_cfg x1e80100_lm[] = { { .name = "lm_0", .id = LM_0, .base = 0x44000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_1, .pingpong = PINGPONG_0, @@ -147,7 +139,7 @@ static const struct dpu_lm_cfg x1e80100_lm[] = { }, { .name = "lm_1", .id = LM_1, .base = 0x45000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_0, .pingpong = PINGPONG_1, @@ -155,28 +147,30 @@ static const struct dpu_lm_cfg x1e80100_lm[] = { }, { .name = "lm_2", .id = LM_2, .base = 0x46000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_3, .pingpong = PINGPONG_2, + .dspp = DSPP_2, }, { .name = "lm_3", .id = LM_3, .base = 0x47000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_2, .pingpong = PINGPONG_3, + .dspp = DSPP_3, }, { .name = "lm_4", .id = LM_4, .base = 0x48000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_5, .pingpong = PINGPONG_4, }, { .name = "lm_5", .id = LM_5, .base = 0x49000, .len = 0x320, - .features = MIXER_SDM845_MASK, + .features = MIXER_MSM8998_MASK, .sblk = &sdm845_lm_sblk, .lm_pair = LM_4, .pingpong = PINGPONG_5, @@ -187,22 +181,18 @@ static const struct dpu_dspp_cfg x1e80100_dspp[] = { { .name = "dspp_0", .id = DSPP_0, .base = 0x54000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_1", .id = DSPP_1, .base = 0x56000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_2", .id = DSPP_2, .base = 0x58000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, { .name = "dspp_3", .id = DSPP_3, .base = 0x5a000, .len = 0x1800, - .features = DSPP_SC7180_MASK, .sblk = &sdm845_dspp_sblk, }, }; @@ -211,55 +201,47 @@ static const struct dpu_pingpong_cfg x1e80100_pp[] = { { .name = "pingpong_0", .id = PINGPONG_0, .base = 0x69000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), }, { .name = "pingpong_1", .id = PINGPONG_1, .base = 0x6a000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_0, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), }, { .name = "pingpong_2", .id = PINGPONG_2, .base = 0x6b000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), }, { .name = "pingpong_3", .id = PINGPONG_3, .base = 0x6c000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_1, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), }, { .name = "pingpong_4", .id = PINGPONG_4, .base = 0x6d000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), }, { .name = "pingpong_5", .id = PINGPONG_5, .base = 0x6e000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_2, .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), }, { - .name = "pingpong_6", .id = PINGPONG_6, + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, .base = 0x66000, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, }, { - .name = "pingpong_7", .id = PINGPONG_7, + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, .base = 0x66400, .len = 0, - .features = BIT(DPU_PINGPONG_DITHER), .sblk = &sc7280_pp_sblk, .merge_3d = MERGE_3D_3, }, @@ -290,22 +272,20 @@ static const struct dpu_dsc_cfg x1e80100_dsc[] = { { .name = "dce_0_0", .id = DSC_0, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_0, }, { .name = "dce_0_1", .id = DSC_1, .base = 0x80000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2), .sblk = &dsc_sblk_1, }, { .name = "dce_1_0", .id = DSC_2, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_0, }, { .name = "dce_1_1", .id = DSC_3, .base = 0x81000, .len = 0x4, - .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN), + .features = BIT(DPU_DSC_NATIVE_42x_EN), .sblk = &dsc_sblk_1, }, }; @@ -314,9 +294,9 @@ static const struct dpu_wb_cfg x1e80100_wb[] = { { .name = "wb_2", .id = WB_2, .base = 0x65000, .len = 0x2c8, - .features = WB_SM8250_MASK, - .format_list = wb2_formats_rgb, - .num_formats = ARRAY_SIZE(wb2_formats_rgb), + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), .xin_id = 6, .vbif_idx = VBIF_RT, .maxlinewidth = 4096, @@ -329,7 +309,6 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { { .name = "intf_0", .id = INTF_0, .base = 0x34000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -338,7 +317,6 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { }, { .name = "intf_1", .id = INTF_1, .base = 0x35000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_0, .prog_fetch_lines_worst_case = 24, @@ -348,7 +326,6 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { }, { .name = "intf_2", .id = INTF_2, .base = 0x36000, .len = 0x300, - .features = INTF_SC7280_MASK, .type = INTF_DSI, .controller_id = MSM_DSI_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -358,7 +335,6 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { }, { .name = "intf_3", .id = INTF_3, .base = 0x37000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_NONE, .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ .prog_fetch_lines_worst_case = 24, @@ -367,7 +343,6 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { }, { .name = "intf_4", .id = INTF_4, .base = 0x38000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, @@ -376,7 +351,6 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { }, { .name = "intf_5", .id = INTF_5, .base = 0x39000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_3, .prog_fetch_lines_worst_case = 24, @@ -385,16 +359,14 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { }, { .name = "intf_6", .id = INTF_6, .base = 0x3A000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_DP, .controller_id = MSM_DP_CONTROLLER_2, .prog_fetch_lines_worst_case = 24, - .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17), - .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16), + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17), }, { .name = "intf_7", .id = INTF_7, .base = 0x3b000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_NONE, .controller_id = MSM_DP_CONTROLLER_2, /* pair with intf_6 for DP MST */ .prog_fetch_lines_worst_case = 24, @@ -403,7 +375,6 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { }, { .name = "intf_8", .id = INTF_8, .base = 0x3c000, .len = 0x280, - .features = INTF_SC7280_MASK, .type = INTF_NONE, .controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_4 for DP MST */ .prog_fetch_lines_worst_case = 24, @@ -451,6 +422,7 @@ const struct dpu_mdss_cfg dpu_x1e80100_cfg = { .mdss_ver = &x1e80100_mdss_ver, .caps = &x1e80100_dpu_caps, .mdp = &x1e80100_mdp, + .cdm = &dpu_cdm_5_x, .ctl_count = ARRAY_SIZE(x1e80100_ctl), .ctl = x1e80100_ctl, .sspp_count = ARRAY_SIZE(x1e80100_sspp), diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 6f0a37f954fe..13cc658065c5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -32,6 +32,26 @@ enum dpu_perf_mode { }; /** + * dpu_core_perf_adjusted_mode_clk - Adjust given mode clock rate according to + * the perf clock factor. + * @crtc_clk_rate - Unadjusted mode clock rate + * @perf_cfg: performance configuration + */ +u64 dpu_core_perf_adjusted_mode_clk(u64 mode_clk_rate, + const struct dpu_perf_cfg *perf_cfg) +{ + u32 clk_factor; + + clk_factor = perf_cfg->clk_inefficiency_factor; + if (clk_factor) { + mode_clk_rate *= clk_factor; + do_div(mode_clk_rate, 100); + } + + return mode_clk_rate; +} + +/** * _dpu_core_perf_calc_bw() - to calculate BW per crtc * @perf_cfg: performance configuration * @crtc: pointer to a crtc @@ -75,28 +95,21 @@ static u64 _dpu_core_perf_calc_clk(const struct dpu_perf_cfg *perf_cfg, struct drm_plane *plane; struct dpu_plane_state *pstate; struct drm_display_mode *mode; - u64 crtc_clk; - u32 clk_factor; + u64 mode_clk; mode = &state->adjusted_mode; - crtc_clk = (u64)mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode); + mode_clk = (u64)mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode); drm_atomic_crtc_for_each_plane(plane, crtc) { pstate = to_dpu_plane_state(plane->state); if (!pstate) continue; - crtc_clk = max(pstate->plane_clk, crtc_clk); + mode_clk = max(pstate->plane_clk, mode_clk); } - clk_factor = perf_cfg->clk_inefficiency_factor; - if (clk_factor) { - crtc_clk *= clk_factor; - do_div(crtc_clk, 100); - } - - return crtc_clk; + return dpu_core_perf_adjusted_mode_clk(mode_clk, perf_cfg); } static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) @@ -118,26 +131,38 @@ static void _dpu_core_perf_calc_crtc(const struct dpu_core_perf *core_perf, return; } - memset(perf, 0, sizeof(struct dpu_core_perf_params)); - - if (core_perf->perf_tune.mode == DPU_PERF_MODE_MINIMUM) { - perf->bw_ctl = 0; - perf->max_per_pipe_ib = 0; - perf->core_clk_rate = 0; - } else if (core_perf->perf_tune.mode == DPU_PERF_MODE_FIXED) { - perf->bw_ctl = core_perf->fix_core_ab_vote; - perf->max_per_pipe_ib = core_perf->fix_core_ib_vote; - perf->core_clk_rate = core_perf->fix_core_clk_rate; - } else { - perf->bw_ctl = _dpu_core_perf_calc_bw(perf_cfg, crtc); - perf->max_per_pipe_ib = perf_cfg->min_dram_ib; - perf->core_clk_rate = _dpu_core_perf_calc_clk(perf_cfg, crtc, state); - } - + perf->bw_ctl = _dpu_core_perf_calc_bw(perf_cfg, crtc); + perf->max_per_pipe_ib = perf_cfg->min_dram_ib; + perf->core_clk_rate = _dpu_core_perf_calc_clk(perf_cfg, crtc, state); DRM_DEBUG_ATOMIC( - "crtc=%d clk_rate=%llu core_ib=%llu core_ab=%llu\n", + "crtc=%d clk_rate=%llu core_ib=%u core_ab=%u\n", crtc->base.id, perf->core_clk_rate, - perf->max_per_pipe_ib, perf->bw_ctl); + perf->max_per_pipe_ib, + (u32)DIV_ROUND_UP_ULL(perf->bw_ctl, 1000)); +} + +static void dpu_core_perf_aggregate(struct drm_device *ddev, + enum dpu_crtc_client_type curr_client_type, + struct dpu_core_perf_params *perf) +{ + struct dpu_crtc_state *dpu_cstate; + struct drm_crtc *tmp_crtc; + + drm_for_each_crtc(tmp_crtc, ddev) { + if (tmp_crtc->enabled && + curr_client_type == dpu_crtc_get_client_type(tmp_crtc)) { + dpu_cstate = to_dpu_crtc_state(tmp_crtc->state); + + perf->max_per_pipe_ib = max(perf->max_per_pipe_ib, + dpu_cstate->new_perf.max_per_pipe_ib); + + perf->bw_ctl += dpu_cstate->new_perf.bw_ctl; + + DRM_DEBUG_ATOMIC("crtc=%d bw=%llu\n", + tmp_crtc->base.id, + dpu_cstate->new_perf.bw_ctl); + } + } } /** @@ -150,11 +175,9 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { u32 bw, threshold; - u64 bw_sum_of_intfs = 0; - enum dpu_crtc_client_type curr_client_type; struct dpu_crtc_state *dpu_cstate; - struct drm_crtc *tmp_crtc; struct dpu_kms *kms; + struct dpu_core_perf_params perf = { 0 }; if (!crtc || !state) { DPU_ERROR("invalid crtc\n"); @@ -172,80 +195,56 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, /* obtain new values */ _dpu_core_perf_calc_crtc(&kms->perf, crtc, state, &dpu_cstate->new_perf); - bw_sum_of_intfs = dpu_cstate->new_perf.bw_ctl; - curr_client_type = dpu_crtc_get_client_type(crtc); + dpu_core_perf_aggregate(crtc->dev, dpu_crtc_get_client_type(crtc), &perf); - drm_for_each_crtc(tmp_crtc, crtc->dev) { - if (tmp_crtc->enabled && - dpu_crtc_get_client_type(tmp_crtc) == curr_client_type && - tmp_crtc != crtc) { - struct dpu_crtc_state *tmp_cstate = - to_dpu_crtc_state(tmp_crtc->state); - - DRM_DEBUG_ATOMIC("crtc:%d bw:%llu ctrl:%d\n", - tmp_crtc->base.id, tmp_cstate->new_perf.bw_ctl, - tmp_cstate->bw_control); + /* convert bandwidth to kb */ + bw = DIV_ROUND_UP_ULL(perf.bw_ctl, 1000); + DRM_DEBUG_ATOMIC("calculated bandwidth=%uk\n", bw); - bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl; - } + threshold = kms->perf.perf_cfg->max_bw_high; - /* convert bandwidth to kb */ - bw = DIV_ROUND_UP_ULL(bw_sum_of_intfs, 1000); - DRM_DEBUG_ATOMIC("calculated bandwidth=%uk\n", bw); + DRM_DEBUG_ATOMIC("final threshold bw limit = %d\n", threshold); - threshold = kms->perf.perf_cfg->max_bw_high; - - DRM_DEBUG_ATOMIC("final threshold bw limit = %d\n", threshold); - - if (!threshold) { - DPU_ERROR("no bandwidth limits specified\n"); - return -E2BIG; - } else if (bw > threshold) { - DPU_ERROR("exceeds bandwidth: %ukb > %ukb\n", bw, - threshold); - return -E2BIG; - } + if (!threshold) { + DPU_ERROR("no bandwidth limits specified\n"); + return -E2BIG; + } else if (bw > threshold) { + DPU_ERROR("exceeds bandwidth: %ukb > %ukb\n", bw, + threshold); + return -E2BIG; } return 0; } static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, - struct drm_crtc *crtc) + struct drm_crtc *crtc) { struct dpu_core_perf_params perf = { 0 }; - enum dpu_crtc_client_type curr_client_type - = dpu_crtc_get_client_type(crtc); - struct drm_crtc *tmp_crtc; - struct dpu_crtc_state *dpu_cstate; int i, ret = 0; - u64 avg_bw; + u32 avg_bw; + u32 peak_bw; if (!kms->num_paths) return 0; - drm_for_each_crtc(tmp_crtc, crtc->dev) { - if (tmp_crtc->enabled && - curr_client_type == - dpu_crtc_get_client_type(tmp_crtc)) { - dpu_cstate = to_dpu_crtc_state(tmp_crtc->state); - - perf.max_per_pipe_ib = max(perf.max_per_pipe_ib, - dpu_cstate->new_perf.max_per_pipe_ib); - - perf.bw_ctl += dpu_cstate->new_perf.bw_ctl; + if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) { + avg_bw = 0; + peak_bw = 0; + } else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_FIXED) { + avg_bw = kms->perf.fix_core_ab_vote; + peak_bw = kms->perf.fix_core_ib_vote; + } else { + dpu_core_perf_aggregate(crtc->dev, dpu_crtc_get_client_type(crtc), &perf); - DRM_DEBUG_ATOMIC("crtc=%d bw=%llu paths:%d\n", - tmp_crtc->base.id, - dpu_cstate->new_perf.bw_ctl, kms->num_paths); - } + avg_bw = div_u64(perf.bw_ctl, 1000); /*Bps_to_icc*/ + peak_bw = perf.max_per_pipe_ib; } - avg_bw = perf.bw_ctl; - do_div(avg_bw, (kms->num_paths * 1000)); /*Bps_to_icc*/ + avg_bw /= kms->num_paths; for (i = 0; i < kms->num_paths; i++) - icc_set_bw(kms->path[i], avg_bw, perf.max_per_pipe_ib); + icc_set_bw(kms->path[i], avg_bw, peak_bw); return ret; } @@ -476,9 +475,9 @@ int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent) &perf->core_clk_rate); debugfs_create_u32("enable_bw_release", 0600, entry, (u32 *)&perf->enable_bw_release); - debugfs_create_u32("threshold_low", 0400, entry, + debugfs_create_u32("low_core_ab", 0400, entry, (u32 *)&perf->perf_cfg->max_bw_low); - debugfs_create_u32("threshold_high", 0400, entry, + debugfs_create_u32("max_core_ab", 0400, entry, (u32 *)&perf->perf_cfg->max_bw_high); debugfs_create_u32("min_core_ib", 0400, entry, (u32 *)&perf->perf_cfg->min_core_ib); @@ -490,9 +489,9 @@ int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent) (u32 *)perf, &dpu_core_perf_mode_fops); debugfs_create_u64("fix_core_clk_rate", 0600, entry, &perf->fix_core_clk_rate); - debugfs_create_u64("fix_core_ib_vote", 0600, entry, + debugfs_create_u32("fix_core_ib_vote", 0600, entry, &perf->fix_core_ib_vote); - debugfs_create_u64("fix_core_ab_vote", 0600, entry, + debugfs_create_u32("fix_core_ab_vote", 0600, entry, &perf->fix_core_ab_vote); return 0; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h index 451bf8021114..3740bc97422c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h @@ -19,7 +19,7 @@ * @core_clk_rate: core clock rate request */ struct dpu_core_perf_params { - u64 max_per_pipe_ib; + u32 max_per_pipe_ib; u64 bw_ctl; u64 core_clk_rate; }; @@ -40,8 +40,8 @@ struct dpu_core_perf_tune { * @perf_tune: debug control for performance tuning * @enable_bw_release: debug control for bandwidth release * @fix_core_clk_rate: fixed core clock request in Hz used in mode 2 - * @fix_core_ib_vote: fixed core ib vote in bps used in mode 2 - * @fix_core_ab_vote: fixed core ab vote in bps used in mode 2 + * @fix_core_ib_vote: fixed core ib vote in KBps used in mode 2 + * @fix_core_ab_vote: fixed core ab vote in KBps used in mode 2 */ struct dpu_core_perf { const struct dpu_perf_cfg *perf_cfg; @@ -50,10 +50,13 @@ struct dpu_core_perf { struct dpu_core_perf_tune perf_tune; u32 enable_bw_release; u64 fix_core_clk_rate; - u64 fix_core_ib_vote; - u64 fix_core_ab_vote; + u32 fix_core_ib_vote; + u32 fix_core_ab_vote; }; +u64 dpu_core_perf_adjusted_mode_clk(u64 clk_rate, + const struct dpu_perf_cfg *perf_cfg); + int dpu_core_perf_crtc_check(struct drm_crtc *crtc, struct drm_crtc_state *state); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 9f6ffd344693..c39f1908ea65 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -200,7 +200,7 @@ static int dpu_crtc_get_lm_crc(struct drm_crtc *crtc, struct dpu_crtc_state *crtc_state) { struct dpu_crtc_mixer *m; - u32 crcs[CRTC_DUAL_MIXERS]; + u32 crcs[CRTC_QUAD_MIXERS]; int rc = 0; int i; @@ -320,14 +320,22 @@ static bool dpu_crtc_get_scanout_position(struct drm_crtc *crtc, } static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer, - struct dpu_plane_state *pstate, const struct msm_format *format) + struct dpu_plane_state *pstate, + const struct msm_format *format, + const struct dpu_mdss_version *mdss_ver) { struct dpu_hw_mixer *lm = mixer->hw_lm; - uint32_t blend_op; - uint32_t fg_alpha, bg_alpha; + u32 blend_op; + u32 fg_alpha, bg_alpha, max_alpha; - fg_alpha = pstate->base.alpha >> 8; - bg_alpha = 0xff - fg_alpha; + if (mdss_ver->core_major_ver < 12) { + max_alpha = 0xff; + fg_alpha = pstate->base.alpha >> 8; + } else { + max_alpha = 0x3ff; + fg_alpha = pstate->base.alpha >> 6; + } + bg_alpha = max_alpha - fg_alpha; /* default to opaque blending */ if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PIXEL_NONE || @@ -337,7 +345,7 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer, } else if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) { blend_op = DPU_BLEND_FG_ALPHA_FG_CONST | DPU_BLEND_BG_ALPHA_FG_PIXEL; - if (fg_alpha != 0xff) { + if (fg_alpha != max_alpha) { bg_alpha = fg_alpha; blend_op |= DPU_BLEND_BG_MOD_ALPHA | DPU_BLEND_BG_INV_MOD_ALPHA; @@ -348,7 +356,7 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer, /* coverage blending */ blend_op = DPU_BLEND_FG_ALPHA_FG_PIXEL | DPU_BLEND_BG_ALPHA_FG_PIXEL; - if (fg_alpha != 0xff) { + if (fg_alpha != max_alpha) { bg_alpha = fg_alpha; blend_op |= DPU_BLEND_FG_MOD_ALPHA | DPU_BLEND_FG_INV_MOD_ALPHA | @@ -369,11 +377,10 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer, static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc) { struct dpu_crtc_state *crtc_state; - int lm_idx, lm_horiz_position; + int lm_idx; crtc_state = to_dpu_crtc_state(crtc->state); - lm_horiz_position = 0; for (lm_idx = 0; lm_idx < crtc_state->num_mixers; lm_idx++) { const struct drm_rect *lm_roi = &crtc_state->lm_bounds[lm_idx]; struct dpu_hw_mixer *hw_lm = crtc_state->mixers[lm_idx].hw_lm; @@ -384,7 +391,7 @@ static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc) cfg.out_width = drm_rect_width(lm_roi); cfg.out_height = drm_rect_height(lm_roi); - cfg.right_mixer = lm_horiz_position++; + cfg.right_mixer = lm_idx & 0x1; cfg.flags = 0; hw_lm->ops.setup_mixer_out(hw_lm, &cfg); } @@ -393,7 +400,7 @@ static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc) static void _dpu_crtc_blend_setup_pipe(struct drm_crtc *crtc, struct drm_plane *plane, struct dpu_crtc_mixer *mixer, - u32 num_mixers, + u32 lms_in_pair, enum dpu_stage stage, const struct msm_format *format, uint64_t modifier, @@ -402,7 +409,7 @@ static void _dpu_crtc_blend_setup_pipe(struct drm_crtc *crtc, struct dpu_hw_stage_cfg *stage_cfg ) { - uint32_t lm_idx; + u32 lm_idx; enum dpu_sspp sspp_idx; struct drm_plane_state *state; @@ -412,7 +419,7 @@ static void _dpu_crtc_blend_setup_pipe(struct drm_crtc *crtc, trace_dpu_crtc_setup_mixer(DRMID(crtc), DRMID(plane), state, to_dpu_plane_state(state), stage_idx, - format->pixel_format, + format->pixel_format, pipe, modifier); DRM_DEBUG_ATOMIC("crtc %d stage:%d - plane %d sspp %d fb %d multirect_idx %d\n", @@ -427,7 +434,7 @@ static void _dpu_crtc_blend_setup_pipe(struct drm_crtc *crtc, stage_cfg->multirect_index[stage][stage_idx] = pipe->multirect_index; /* blend config update */ - for (lm_idx = 0; lm_idx < num_mixers; lm_idx++) + for (lm_idx = 0; lm_idx < lms_in_pair; lm_idx++) mixer[lm_idx].lm_ctl->ops.update_pending_flush_sspp(mixer[lm_idx].lm_ctl, sspp_idx); } @@ -442,12 +449,13 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct dpu_plane_state *pstate = NULL; const struct msm_format *format; struct dpu_hw_ctl *ctl = mixer->lm_ctl; - - uint32_t lm_idx; + u32 lm_idx, stage, i, pipe_idx, head_pipe_in_stage, lms_in_pair; bool bg_alpha_enable = false; - DECLARE_BITMAP(fetch_active, SSPP_MAX); + DECLARE_BITMAP(active_fetch, SSPP_MAX); + DECLARE_BITMAP(active_pipes, SSPP_MAX); - memset(fetch_active, 0, sizeof(fetch_active)); + memset(active_fetch, 0, sizeof(active_fetch)); + memset(active_pipes, 0, sizeof(active_pipes)); drm_atomic_crtc_for_each_plane(plane, crtc) { state = plane->state; if (!state) @@ -464,25 +472,31 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, if (pstate->stage == DPU_STAGE_BASE && format->alpha_enable) bg_alpha_enable = true; - set_bit(pstate->pipe.sspp->idx, fetch_active); - _dpu_crtc_blend_setup_pipe(crtc, plane, - mixer, cstate->num_mixers, - pstate->stage, - format, fb ? fb->modifier : 0, - &pstate->pipe, 0, stage_cfg); - - if (pstate->r_pipe.sspp) { - set_bit(pstate->r_pipe.sspp->idx, fetch_active); - _dpu_crtc_blend_setup_pipe(crtc, plane, - mixer, cstate->num_mixers, - pstate->stage, - format, fb ? fb->modifier : 0, - &pstate->r_pipe, 1, stage_cfg); + /* loop pipe per mixer pair with config in stage structure */ + for (stage = 0; stage < STAGES_PER_PLANE; stage++) { + head_pipe_in_stage = stage * PIPES_PER_STAGE; + for (i = 0; i < PIPES_PER_STAGE; i++) { + pipe_idx = i + head_pipe_in_stage; + if (!pstate->pipe[pipe_idx].sspp) + continue; + lms_in_pair = min(cstate->num_mixers - (stage * PIPES_PER_STAGE), + PIPES_PER_STAGE); + set_bit(pstate->pipe[pipe_idx].sspp->idx, active_fetch); + set_bit(pstate->pipe[pipe_idx].sspp->idx, active_pipes); + _dpu_crtc_blend_setup_pipe(crtc, plane, + &mixer[head_pipe_in_stage], + lms_in_pair, + pstate->stage, + format, fb ? fb->modifier : 0, + &pstate->pipe[pipe_idx], i, + &stage_cfg[stage]); + } } /* blend config update */ for (lm_idx = 0; lm_idx < cstate->num_mixers; lm_idx++) { - _dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate, format); + _dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate, format, + ctl->mdss_ver); if (bg_alpha_enable && !format->alpha_enable) mixer[lm_idx].mixer_op_mode = 0; @@ -492,8 +506,11 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, } } + if (ctl->ops.set_active_fetch_pipes) + ctl->ops.set_active_fetch_pipes(ctl, active_fetch); + if (ctl->ops.set_active_pipes) - ctl->ops.set_active_pipes(ctl, fetch_active); + ctl->ops.set_active_pipes(ctl, active_pipes); _dpu_crtc_program_lm_output_roi(crtc); } @@ -509,7 +526,8 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) struct dpu_crtc_mixer *mixer = cstate->mixers; struct dpu_hw_ctl *ctl; struct dpu_hw_mixer *lm; - struct dpu_hw_stage_cfg stage_cfg; + struct dpu_hw_stage_cfg stage_cfg[STAGES_PER_PLANE]; + DECLARE_BITMAP(active_lms, LM_MAX); int i; DRM_DEBUG_ATOMIC("%s\n", dpu_crtc->name); @@ -519,12 +537,20 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) if (mixer[i].lm_ctl->ops.clear_all_blendstages) mixer[i].lm_ctl->ops.clear_all_blendstages( mixer[i].lm_ctl); + if (mixer[i].lm_ctl->ops.set_active_fetch_pipes) + mixer[i].lm_ctl->ops.set_active_fetch_pipes(mixer[i].lm_ctl, NULL); + if (mixer[i].lm_ctl->ops.set_active_pipes) + mixer[i].lm_ctl->ops.set_active_pipes(mixer[i].lm_ctl, NULL); + + if (mixer[i].hw_lm->ops.clear_all_blendstages) + mixer[i].hw_lm->ops.clear_all_blendstages(mixer[i].hw_lm); } /* initialize stage cfg */ - memset(&stage_cfg, 0, sizeof(struct dpu_hw_stage_cfg)); + memset(&stage_cfg, 0, sizeof(stage_cfg)); + memset(active_lms, 0, sizeof(active_lms)); - _dpu_crtc_blend_setup_mixer(crtc, dpu_crtc, mixer, &stage_cfg); + _dpu_crtc_blend_setup_mixer(crtc, dpu_crtc, mixer, stage_cfg); for (i = 0; i < cstate->num_mixers; i++) { ctl = mixer[i].lm_ctl; @@ -536,13 +562,26 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) ctl->ops.update_pending_flush_mixer(ctl, mixer[i].hw_lm->idx); + set_bit(lm->idx, active_lms); + if (ctl->ops.set_active_lms) + ctl->ops.set_active_lms(ctl, active_lms); + DRM_DEBUG_ATOMIC("lm %d, op_mode 0x%X, ctl %d\n", mixer[i].hw_lm->idx - LM_0, mixer[i].mixer_op_mode, ctl->idx - CTL_0); - ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx, - &stage_cfg); + /* + * call dpu_hw_ctl_setup_blendstage() to blend layers per stage cfg. + * stage data is shared between PIPES_PER_STAGE pipes. + */ + if (ctl->ops.setup_blendstage) + ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx, + &stage_cfg[i / PIPES_PER_STAGE]); + + if (lm->ops.setup_blendstage) + lm->ops.setup_blendstage(lm, mixer[i].hw_lm->idx, + &stage_cfg[i / PIPES_PER_STAGE]); } } @@ -563,7 +602,7 @@ static void _dpu_crtc_complete_flip(struct drm_crtc *crtc) spin_lock_irqsave(&dev->event_lock, flags); if (dpu_crtc->event) { - DRM_DEBUG_VBL("%s: send event: %pK\n", dpu_crtc->name, + DRM_DEBUG_VBL("%s: send event: %p\n", dpu_crtc->name, dpu_crtc->event); trace_dpu_crtc_complete_flip(DRMID(crtc)); drm_crtc_send_vblank_event(crtc, dpu_crtc->event); @@ -709,7 +748,7 @@ void dpu_crtc_frame_event_cb(struct drm_crtc *crtc, u32 event) fevent->event = event; fevent->crtc = crtc; fevent->ts = ktime_get(); - kthread_queue_work(priv->event_thread[crtc_id].worker, &fevent->work); + kthread_queue_work(priv->kms->event_thread[crtc_id].worker, &fevent->work); } /** @@ -732,6 +771,13 @@ static int _dpu_crtc_check_and_setup_lm_bounds(struct drm_crtc *crtc, struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); int i; + /* if we cannot merge 2 LMs (no 3d mux) better to fail earlier + * before even checking the width after the split + */ + if (!dpu_kms->catalog->caps->has_3d_merge && + adj_mode->hdisplay > dpu_kms->catalog->caps->max_mixer_width) + return -E2BIG; + for (i = 0; i < cstate->num_mixers; i++) { struct drm_rect *r = &cstate->lm_bounds[i]; r->x1 = crtc_split_width * i; @@ -871,7 +917,7 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, dev = crtc->dev; priv = dev->dev_private; - if (crtc->index >= ARRAY_SIZE(priv->event_thread)) { + if (crtc->index >= ARRAY_SIZE(priv->kms->event_thread)) { DPU_ERROR("invalid crtc index[%d]\n", crtc->index); return; } @@ -946,6 +992,45 @@ static int _dpu_crtc_wait_for_frame_done(struct drm_crtc *crtc) return rc; } +static int dpu_crtc_kickoff_clone_mode(struct drm_crtc *crtc) +{ + struct drm_encoder *encoder; + struct drm_encoder *rt_encoder = NULL, *wb_encoder = NULL; + struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); + + /* Find encoder for real time display */ + drm_for_each_encoder_mask(encoder, crtc->dev, + crtc->state->encoder_mask) { + if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) + wb_encoder = encoder; + else + rt_encoder = encoder; + } + + if (!rt_encoder || !wb_encoder) { + DRM_DEBUG_ATOMIC("real time or wb encoder not found\n"); + return -EINVAL; + } + + dpu_encoder_prepare_for_kickoff(wb_encoder); + dpu_encoder_prepare_for_kickoff(rt_encoder); + + dpu_vbif_clear_errors(dpu_kms); + + /* + * Kickoff real time encoder last as it's the encoder that + * will do the flush + */ + dpu_encoder_kickoff(wb_encoder); + dpu_encoder_kickoff(rt_encoder); + + /* Don't start frame done timers until the kickoffs have finished */ + dpu_encoder_start_frame_done_timer(wb_encoder); + dpu_encoder_start_frame_done_timer(rt_encoder); + + return 0; +} + /** * dpu_crtc_commit_kickoff - trigger kickoff of the commit for this crtc * @crtc: Pointer to drm crtc object @@ -974,13 +1059,27 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc) goto end; } } - /* - * Encoder will flush/start now, unless it has a tx pending. If so, it - * may delay and flush at an irq event (e.g. ppdone) - */ - drm_for_each_encoder_mask(encoder, crtc->dev, - crtc->state->encoder_mask) - dpu_encoder_prepare_for_kickoff(encoder); + + if (drm_crtc_in_clone_mode(crtc->state)) { + if (dpu_crtc_kickoff_clone_mode(crtc)) + goto end; + } else { + /* + * Encoder will flush/start now, unless it has a tx pending. + * If so, it may delay and flush at an irq event (e.g. ppdone) + */ + drm_for_each_encoder_mask(encoder, crtc->dev, + crtc->state->encoder_mask) + dpu_encoder_prepare_for_kickoff(encoder); + + dpu_vbif_clear_errors(dpu_kms); + + drm_for_each_encoder_mask(encoder, crtc->dev, + crtc->state->encoder_mask) { + dpu_encoder_kickoff(encoder); + dpu_encoder_start_frame_done_timer(encoder); + } + } if (atomic_inc_return(&dpu_crtc->frame_pending) == 1) { /* acquire bandwidth and other resources */ @@ -990,11 +1089,6 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc) dpu_crtc->play_count++; - dpu_vbif_clear_errors(dpu_kms); - - drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) - dpu_encoder_kickoff(encoder); - reinit_completion(&dpu_crtc->frame_done_comp); end: @@ -1182,6 +1276,205 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate) return false; } +static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state) +{ + int total_planes = crtc->dev->mode_config.num_total_plane; + struct drm_atomic_state *state = crtc_state->state; + struct dpu_global_state *global_state; + struct drm_plane_state **states; + struct drm_plane *plane; + int ret; + + global_state = dpu_kms_get_global_state(crtc_state->state); + if (IS_ERR(global_state)) + return PTR_ERR(global_state); + + dpu_rm_release_all_sspp(global_state, crtc); + + if (!crtc_state->enable) + return 0; + + states = kcalloc(total_planes, sizeof(*states), GFP_KERNEL); + if (!states) + return -ENOMEM; + + drm_atomic_crtc_state_for_each_plane(plane, crtc_state) { + struct drm_plane_state *plane_state = + drm_atomic_get_plane_state(state, plane); + + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + goto done; + } + + states[plane_state->normalized_zpos] = plane_state; + } + + ret = dpu_assign_plane_resources(global_state, state, crtc, states, total_planes); + +done: + kfree(states); + return ret; +} + +#define MAX_CHANNELS_PER_CRTC PIPES_PER_PLANE +#define MAX_HDISPLAY_SPLIT 1080 + +static struct msm_display_topology dpu_crtc_get_topology( + struct drm_crtc *crtc, + struct dpu_kms *dpu_kms, + struct drm_crtc_state *crtc_state) +{ + struct drm_display_mode *mode = &crtc_state->adjusted_mode; + struct msm_display_topology topology = {0}; + struct drm_encoder *drm_enc; + u32 num_rt_intf; + + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) + dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state, + &crtc_state->adjusted_mode); + + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state); + + /* + * Datapath topology selection + * + * Dual display + * 2 LM, 2 INTF ( Split display using 2 interfaces) + * + * If DSC is enabled, try to use 4:4:2 topology if there is enough + * resource. Otherwise, use 2:2:2 topology. + * + * Single display + * 1 LM, 1 INTF + * 2 LM, 1 INTF (stream merge to support high resolution interfaces) + * + * If DSC is enabled, use 2:2:1 topology + * + * Add dspps to the reservation requirements if ctm is requested + * + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not + * enabled. This is because in cases where CWB is enabled, num_intf will + * count both the WB and real-time phys encoders. + * + * For non-DSC CWB usecases, have the num_lm be decided by the + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check. + */ + + num_rt_intf = topology.num_intf; + if (topology.cwb_enabled) + num_rt_intf--; + + if (topology.num_dsc) { + if (dpu_kms->catalog->dsc_count >= num_rt_intf * 2) + topology.num_dsc = num_rt_intf * 2; + else + topology.num_dsc = num_rt_intf; + topology.num_lm = topology.num_dsc; + } else if (num_rt_intf == 2) { + topology.num_lm = 2; + } else if (dpu_kms->catalog->caps->has_3d_merge) { + topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; + } else { + topology.num_lm = 1; + } + + if (crtc_state->ctm) + topology.num_dspp = topology.num_lm; + + return topology; +} + +static int dpu_crtc_assign_resources(struct drm_crtc *crtc, + struct drm_crtc_state *crtc_state) +{ + struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_CRTC]; + struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_CRTC]; + struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_CRTC]; + int i, num_lm, num_ctl, num_dspp; + struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); + struct dpu_global_state *global_state; + struct dpu_crtc_state *cstate; + struct msm_display_topology topology; + int ret; + + /* + * Release and Allocate resources on every modeset + */ + global_state = dpu_kms_get_global_state(crtc_state->state); + if (IS_ERR(global_state)) + return PTR_ERR(global_state); + + dpu_rm_release(global_state, crtc); + + if (!crtc_state->enable) + return 0; + + topology = dpu_crtc_get_topology(crtc, dpu_kms, crtc_state); + ret = dpu_rm_reserve(&dpu_kms->rm, global_state, + crtc_state->crtc, &topology); + if (ret) + return ret; + + cstate = to_dpu_crtc_state(crtc_state); + + num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, + crtc_state->crtc, + DPU_HW_BLK_CTL, hw_ctl, + ARRAY_SIZE(hw_ctl)); + num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, + crtc_state->crtc, + DPU_HW_BLK_LM, hw_lm, + ARRAY_SIZE(hw_lm)); + num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, + crtc_state->crtc, + DPU_HW_BLK_DSPP, hw_dspp, + ARRAY_SIZE(hw_dspp)); + + for (i = 0; i < num_lm; i++) { + int ctl_idx = (i < num_ctl) ? i : (num_ctl-1); + + cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]); + cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]); + if (i < num_dspp) + cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]); + } + + cstate->num_mixers = num_lm; + + return 0; +} + +/** + * dpu_crtc_check_mode_changed: check if full modeset is required + * @old_crtc_state: Previous CRTC state + * @new_crtc_state: Corresponding CRTC state to be checked + * + * Check if the changes in the object properties demand full mode set. + */ +int dpu_crtc_check_mode_changed(struct drm_crtc_state *old_crtc_state, + struct drm_crtc_state *new_crtc_state) +{ + struct drm_encoder *drm_enc; + struct drm_crtc *crtc = new_crtc_state->crtc; + bool clone_mode_enabled = drm_crtc_in_clone_mode(old_crtc_state); + bool clone_mode_requested = drm_crtc_in_clone_mode(new_crtc_state); + + DRM_DEBUG_ATOMIC("%d\n", crtc->base.id); + + /* there might be cases where encoder needs a modeset too */ + drm_for_each_encoder_mask(drm_enc, crtc->dev, new_crtc_state->encoder_mask) { + if (dpu_encoder_needs_modeset(drm_enc, new_crtc_state->state)) + new_crtc_state->mode_changed = true; + } + + if ((clone_mode_requested && !clone_mode_enabled) || + (!clone_mode_requested && clone_mode_enabled)) + new_crtc_state->mode_changed = true; + + return 0; +} + static int dpu_crtc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) { @@ -1197,6 +1490,20 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state); + /* don't reallocate resources if only ACTIVE has beeen changed */ + if (crtc_state->mode_changed || crtc_state->connectors_changed) { + rc = dpu_crtc_assign_resources(crtc, crtc_state); + if (rc < 0) + return rc; + } + + if (dpu_use_virtual_planes && + (crtc_state->planes_changed || crtc_state->zpos_changed)) { + rc = dpu_crtc_reassign_planes(crtc, crtc_state); + if (rc < 0) + return rc; + } + if (!crtc_state->enable || !drm_atomic_crtc_effectively_active(crtc_state)) { DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n", crtc->base.id, crtc_state->enable, @@ -1207,10 +1514,6 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, DRM_DEBUG_ATOMIC("%s: check\n", dpu_crtc->name); - /* force a full mode set if active state changed */ - if (crtc_state->active_changed) - crtc_state->mode_changed = true; - if (cstate->num_mixers) { rc = _dpu_crtc_check_and_setup_lm_bounds(crtc, crtc_state); if (rc) @@ -1250,6 +1553,27 @@ static enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) { struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); + u64 adjusted_mode_clk; + + /* if there is no 3d_mux block we cannot merge LMs so we cannot + * split the large layer into 2 LMs, filter out such modes + */ + if (!dpu_kms->catalog->caps->has_3d_merge && + mode->hdisplay > dpu_kms->catalog->caps->max_mixer_width) + return MODE_BAD_HVALUE; + + adjusted_mode_clk = dpu_core_perf_adjusted_mode_clk(mode->clock, + dpu_kms->perf.perf_cfg); + + if (dpu_kms->catalog->caps->has_3d_merge) + adjusted_mode_clk /= 2; + + /* + * The given mode, adjusted for the perf clock factor, should not exceed + * the max core clock rate + */ + if (dpu_kms->perf.max_core_clk_rate < adjusted_mode_clk * 1000) + return MODE_CLOCK_HIGH; /* * max crtc width is equal to the max mixer width * 2 and max height is 4K @@ -1296,6 +1620,17 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool en) return 0; } +/** + * dpu_crtc_get_num_lm - Get mixer number in this CRTC pipeline + * @state: Pointer to drm crtc state object + */ +unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state) +{ + struct dpu_crtc_state *cstate = to_dpu_crtc_state(state); + + return cstate->num_mixers; +} + #ifdef CONFIG_DEBUG_FS static int _dpu_debugfs_status_show(struct seq_file *s, void *data) { @@ -1378,15 +1713,15 @@ static int _dpu_debugfs_status_show(struct seq_file *s, void *data) seq_printf(s, "\tdst x:%4d dst_y:%4d dst_w:%4d dst_h:%4d\n", state->crtc_x, state->crtc_y, state->crtc_w, state->crtc_h); - seq_printf(s, "\tsspp[0]:%s\n", - pstate->pipe.sspp->cap->name); - seq_printf(s, "\tmultirect[0]: mode: %d index: %d\n", - pstate->pipe.multirect_mode, pstate->pipe.multirect_index); - if (pstate->r_pipe.sspp) { - seq_printf(s, "\tsspp[1]:%s\n", - pstate->r_pipe.sspp->cap->name); - seq_printf(s, "\tmultirect[1]: mode: %d index: %d\n", - pstate->r_pipe.multirect_mode, pstate->r_pipe.multirect_index); + + for (i = 0; i < PIPES_PER_PLANE; i++) { + if (!pstate->pipe[i].sspp) + continue; + seq_printf(s, "\tsspp[%d]:%s\n", + i, pstate->pipe[i].sspp->cap->name); + seq_printf(s, "\tmultirect[%d]: mode: %d index: %d\n", + i, pstate->pipe[i].multirect_mode, + pstate->pipe[i].multirect_index); } seq_puts(s, "\n"); @@ -1423,8 +1758,9 @@ static int dpu_crtc_debugfs_state_show(struct seq_file *s, void *v) seq_printf(s, "intf_mode: %d\n", dpu_crtc_get_intf_mode(crtc)); seq_printf(s, "core_clk_rate: %llu\n", dpu_crtc->cur_perf.core_clk_rate); - seq_printf(s, "bw_ctl: %llu\n", dpu_crtc->cur_perf.bw_ctl); - seq_printf(s, "max_per_pipe_ib: %llu\n", + seq_printf(s, "bw_ctl: %uk\n", + (u32)DIV_ROUND_UP_ULL(dpu_crtc->cur_perf.bw_ctl, 1000)); + seq_printf(s, "max_per_pipe_ib: %u\n", dpu_crtc->cur_perf.max_per_pipe_ib); return 0; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index 0b148f3ce0d7..455073c7025b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -210,7 +210,7 @@ struct dpu_crtc_state { bool bw_control; bool bw_split_vote; - struct drm_rect lm_bounds[CRTC_DUAL_MIXERS]; + struct drm_rect lm_bounds[CRTC_QUAD_MIXERS]; uint64_t input_fence_timeout_ns; @@ -218,10 +218,10 @@ struct dpu_crtc_state { /* HW Resources reserved for the crtc */ u32 num_mixers; - struct dpu_crtc_mixer mixers[CRTC_DUAL_MIXERS]; + struct dpu_crtc_mixer mixers[CRTC_QUAD_MIXERS]; u32 num_ctls; - struct dpu_hw_ctl *hw_ctls[CRTC_DUAL_MIXERS]; + struct dpu_hw_ctl *hw_ctls[CRTC_QUAD_MIXERS]; enum dpu_crtc_crc_source crc_source; int crc_frame_skip_count; @@ -239,6 +239,9 @@ static inline int dpu_crtc_frame_pending(struct drm_crtc *crtc) return crtc ? atomic_read(&to_dpu_crtc(crtc)->frame_pending) : -EINVAL; } +int dpu_crtc_check_mode_changed(struct drm_crtc_state *old_crtc_state, + struct drm_crtc_state *new_crtc_state); + int dpu_crtc_vblank(struct drm_crtc *crtc, bool en); void dpu_crtc_vblank_callback(struct drm_crtc *crtc); @@ -264,4 +267,6 @@ static inline enum dpu_crtc_client_type dpu_crtc_get_client_type( void dpu_crtc_frame_event_cb(struct drm_crtc *crtc, u32 event); +unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state); + #endif /* _DPU_CRTC_H_ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 83de7564e2c1..d1cfe81a3373 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2,7 +2,7 @@ /* * Copyright (C) 2013 Red Hat * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. * * Author: Rob Clark <robdclark@gmail.com> */ @@ -24,6 +24,7 @@ #include "dpu_hw_catalog.h" #include "dpu_hw_intf.h" #include "dpu_hw_ctl.h" +#include "dpu_hw_cwb.h" #include "dpu_hw_dspp.h" #include "dpu_hw_dsc.h" #include "dpu_hw_merge3d.h" @@ -54,12 +55,11 @@ #define MAX_PHYS_ENCODERS_PER_VIRTUAL \ (MAX_H_TILES_PER_DISPLAY * NUM_PHYS_ENCODER_TYPES) -#define MAX_CHANNELS_PER_ENC 2 +#define MAX_CHANNELS_PER_ENC 4 +#define MAX_CWB_PER_ENC 2 #define IDLE_SHORT_TIMEOUT 1 -#define MAX_HDISPLAY_SPLIT 1080 - /* timeout in frames waiting for frame done */ #define DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES 5 @@ -135,8 +135,12 @@ enum dpu_enc_rc_states { * @cur_slave: As above but for the slave encoder. * @hw_pp: Handle to the pingpong blocks used for the display. No. * pingpong blocks can be different than num_phys_encs. + * @hw_cwb: Handle to the CWB muxes used for concurrent writeback + * display. Number of CWB muxes can be different than + * num_phys_encs. * @hw_dsc: Handle to the DSC blocks used for the display. * @dsc_mask: Bitmask of used DSC blocks. + * @cwb_mask: Bitmask of used CWB muxes * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped * for partial update right-only cases, such as pingpong * split where virtual pingpong does not generate IRQs @@ -179,9 +183,11 @@ struct dpu_encoder_virt { struct dpu_encoder_phys *cur_master; struct dpu_encoder_phys *cur_slave; struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC]; + struct dpu_hw_cwb *hw_cwb[MAX_CWB_PER_ENC]; struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; unsigned int dsc_mask; + unsigned int cwb_mask; bool intfs_swapped; @@ -259,7 +265,7 @@ bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc) mode = &phys_enc->cached_mode; return phys_enc->hw_intf->cap->type == INTF_DP && - msm_dp_needs_periph_flush(priv->dp[disp_info->h_tile_instance[0]], mode); + msm_dp_needs_periph_flush(priv->kms->dp[disp_info->h_tile_instance[0]], mode); } /** @@ -278,9 +284,9 @@ bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc) index = disp_info->h_tile_instance[0]; if (disp_info->intf_type == INTF_DP) - return msm_dp_wide_bus_available(priv->dp[index]); + return msm_dp_wide_bus_available(priv->kms->dp[index]); else if (disp_info->intf_type == INTF_DSI) - return msm_dsi_wide_bus_enabled(priv->dsi[index]); + return msm_dsi_wide_bus_enabled(priv->kms->dsi[index]); return false; } @@ -622,9 +628,9 @@ bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc) if (dpu_enc->phys_encs[i]) intf_count++; - /* See dpu_encoder_get_topology, we only support 2:2:1 topology */ - if (dpu_enc->dsc) - num_dsc = 2; + for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) + if (dpu_enc->hw_dsc[i]) + num_dsc++; return (num_dsc > 0) && (num_dsc > intf_count); } @@ -642,135 +648,45 @@ struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc) int index = dpu_enc->disp_info.h_tile_instance[0]; if (dpu_enc->disp_info.intf_type == INTF_DSI) - return msm_dsi_get_dsc_config(priv->dsi[index]); + return msm_dsi_get_dsc_config(priv->kms->dsi[index]); return NULL; } -static struct msm_display_topology dpu_encoder_get_topology( - struct dpu_encoder_virt *dpu_enc, - struct dpu_kms *dpu_kms, - struct drm_display_mode *mode, - struct drm_crtc_state *crtc_state, - struct drm_dsc_config *dsc) -{ - struct msm_display_topology topology = {0}; - int i, intf_count = 0; - - for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++) - if (dpu_enc->phys_encs[i]) - intf_count++; - - /* Datapath topology selection - * - * Dual display - * 2 LM, 2 INTF ( Split display using 2 interfaces) - * - * Single display - * 1 LM, 1 INTF - * 2 LM, 1 INTF (stream merge to support high resolution interfaces) - * - * Add dspps to the reservation requirements if ctm is requested - */ - if (intf_count == 2) - topology.num_lm = 2; - else if (!dpu_kms->catalog->caps->has_3d_merge) - topology.num_lm = 1; - else - topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; - - if (crtc_state->ctm) - topology.num_dspp = topology.num_lm; - - topology.num_intf = intf_count; - - if (dsc) { - /* - * In case of Display Stream Compression (DSC), we would use - * 2 DSC encoders, 2 layer mixers and 1 interface - * this is power optimal and can drive up to (including) 4k - * screens - */ - topology.num_dsc = 2; - topology.num_lm = 2; - topology.num_intf = 1; - } - - return topology; -} - -static void dpu_encoder_assign_crtc_resources(struct dpu_kms *dpu_kms, - struct drm_encoder *drm_enc, - struct dpu_global_state *global_state, - struct drm_crtc_state *crtc_state) -{ - struct dpu_crtc_state *cstate; - struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC]; - struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC]; - struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC]; - int num_lm, num_ctl, num_dspp, i; - - cstate = to_dpu_crtc_state(crtc_state); - - memset(cstate->mixers, 0, sizeof(cstate->mixers)); - - num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, - drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl)); - num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, - drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm)); - num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, - drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp, - ARRAY_SIZE(hw_dspp)); - - for (i = 0; i < num_lm; i++) { - int ctl_idx = (i < num_ctl) ? i : (num_ctl-1); - - cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]); - cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]); - cstate->mixers[i].hw_dspp = i < num_dspp ? to_dpu_hw_dspp(hw_dspp[i]) : NULL; - } - - cstate->num_mixers = num_lm; -} - -static int dpu_encoder_virt_atomic_check( - struct drm_encoder *drm_enc, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) +void dpu_encoder_update_topology(struct drm_encoder *drm_enc, + struct msm_display_topology *topology, + struct drm_atomic_state *state, + const struct drm_display_mode *adj_mode) { - struct dpu_encoder_virt *dpu_enc; - struct msm_drm_private *priv; - struct dpu_kms *dpu_kms; - struct drm_display_mode *adj_mode; - struct msm_display_topology topology; - struct msm_display_info *disp_info; - struct dpu_global_state *global_state; + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); + struct msm_drm_private *priv = dpu_enc->base.dev->dev_private; + struct msm_display_info *disp_info = &dpu_enc->disp_info; + struct drm_connector *connector; + struct drm_connector_state *conn_state; struct drm_framebuffer *fb; struct drm_dsc_config *dsc; - int ret = 0; - - if (!drm_enc || !crtc_state || !conn_state) { - DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n", - drm_enc != NULL, crtc_state != NULL, conn_state != NULL); - return -EINVAL; - } - dpu_enc = to_dpu_encoder_virt(drm_enc); - DPU_DEBUG_ENC(dpu_enc, "\n"); - - priv = drm_enc->dev->dev_private; - disp_info = &dpu_enc->disp_info; - dpu_kms = to_dpu_kms(priv->kms); - adj_mode = &crtc_state->adjusted_mode; - global_state = dpu_kms_get_global_state(crtc_state->state); - if (IS_ERR(global_state)) - return PTR_ERR(global_state); + int i; - trace_dpu_enc_atomic_check(DRMID(drm_enc)); + for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++) + if (dpu_enc->phys_encs[i]) + topology->num_intf++; dsc = dpu_encoder_get_dsc_config(drm_enc); - topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state, dsc); + /* + * Set DSC number as 1 to mark the enabled status, will be adjusted + * in dpu_crtc_get_topology() + */ + if (dsc) + topology->num_dsc = 1; + + connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc); + if (!connector) + return; + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (!conn_state) + return; /* * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it. @@ -781,34 +697,48 @@ static int dpu_encoder_virt_atomic_check( fb = conn_state->writeback_job->fb; if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) - topology.needs_cdm = true; + topology->num_cdm++; } else if (disp_info->intf_type == INTF_DP) { - if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode)) - topology.needs_cdm = true; + if (msm_dp_is_yuv_420_enabled(priv->kms->dp[disp_info->h_tile_instance[0]], + adj_mode)) + topology->num_cdm++; } +} - if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm) - crtc_state->mode_changed = true; - else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm) - crtc_state->mode_changed = true; - /* - * Release and Allocate resources on every modeset - * Dont allocate when active is false. - */ - if (drm_atomic_crtc_needs_modeset(crtc_state)) { - dpu_rm_release(global_state, drm_enc); +bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state) +{ + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_framebuffer *fb; + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); - if (!crtc_state->active_changed || crtc_state->enable) - ret = dpu_rm_reserve(&dpu_kms->rm, global_state, - drm_enc, crtc_state, topology); - if (!ret) - dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc, - global_state, crtc_state); - } + if (!drm_enc || !state) + return false; - trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags); + connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc); + if (!connector) + return false; - return ret; + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (!conn_state) + return false; + + /** + * These checks are duplicated from dpu_encoder_update_topology() since + * CRTC and encoder don't hold topology information + */ + if (dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) { + fb = conn_state->writeback_job->fb; + if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) { + if (!dpu_enc->cur_master->hw_cdm) + return true; + } else { + if (dpu_enc->cur_master->hw_cdm) + return true; + } + } + + return false; } static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc, @@ -1043,7 +973,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, return 0; } - queue_delayed_work(priv->wq, &dpu_enc->delayed_off_work, + queue_delayed_work(priv->kms->wq, &dpu_enc->delayed_off_work, msecs_to_jiffies(dpu_enc->idle_timeout)); trace_dpu_enc_rc(DRMID(drm_enc), sw_event, @@ -1219,8 +1149,12 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC]; - int num_ctl, num_pp, num_dsc; + struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC]; + int num_ctl, num_pp, num_dsc, num_pp_per_intf; + int num_cwb = 0; + bool is_cwb_encoder; unsigned int dsc_mask = 0; + unsigned int cwb_mask = 0; int i; if (!drm_enc) { @@ -1233,6 +1167,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, priv = drm_enc->dev->dev_private; dpu_kms = to_dpu_kms(priv->kms); + is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) && + dpu_enc->disp_info.intf_type == INTF_WB; global_state = dpu_kms_get_existing_global_state(dpu_kms); if (IS_ERR_OR_NULL(global_state)) { @@ -1243,18 +1179,38 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, trace_dpu_enc_mode_set(DRMID(drm_enc)); /* Query resource that have been reserved in atomic check step. */ - num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, - drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp, - ARRAY_SIZE(hw_pp)); + if (is_cwb_encoder) { + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, + drm_enc->crtc, + DPU_HW_BLK_DCWB_PINGPONG, + hw_pp, ARRAY_SIZE(hw_pp)); + num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, + drm_enc->crtc, + DPU_HW_BLK_CWB, + hw_cwb, ARRAY_SIZE(hw_cwb)); + } else { + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, + drm_enc->crtc, + DPU_HW_BLK_PINGPONG, hw_pp, + ARRAY_SIZE(hw_pp)); + } + + for (i = 0; i < num_cwb; i++) { + dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]); + cwb_mask |= BIT(dpu_enc->hw_cwb[i]->idx - CWB_0); + } + + dpu_enc->cwb_mask = cwb_mask; + num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, - drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl)); + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl)); for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i]) : NULL; num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, - drm_enc->base.id, DPU_HW_BLK_DSC, + drm_enc->crtc, DPU_HW_BLK_DSC, hw_dsc, ARRAY_SIZE(hw_dsc)); for (i = 0; i < num_dsc; i++) { dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]); @@ -1268,22 +1224,32 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, struct dpu_hw_blk *hw_cdm = NULL; dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, - drm_enc->base.id, DPU_HW_BLK_CDM, + drm_enc->crtc, DPU_HW_BLK_CDM, &hw_cdm, 1); dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL; } + /* + * There may be 4 PP and 2 INTF for quad pipe case, so INTF is not + * mapped to PP 1:1. Let's calculate the stride with pipe/INTF + */ + num_pp_per_intf = num_pp / dpu_enc->num_phys_encs; + for (i = 0; i < dpu_enc->num_phys_encs; i++) { struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; - phys->hw_pp = dpu_enc->hw_pp[i]; + phys->hw_pp = dpu_enc->hw_pp[num_pp_per_intf * i]; if (!phys->hw_pp) { DPU_ERROR_ENC(dpu_enc, "no pp block assigned at idx: %d\n", i); return; } - phys->hw_ctl = i < num_ctl ? to_dpu_hw_ctl(hw_ctl[i]) : NULL; + /* Use first (and only) CTL if active CTLs are supported */ + if (num_ctl == 1) + phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[0]); + else + phys->hw_ctl = i < num_ctl ? to_dpu_hw_ctl(hw_ctl[i]) : NULL; if (!phys->hw_ctl) { DPU_ERROR_ENC(dpu_enc, "no ctl block assigned at idx: %d\n", i); @@ -1447,7 +1413,7 @@ static void dpu_encoder_virt_atomic_disable(struct drm_encoder *drm_enc, /* after phys waits for frame-done, should be no more frames pending */ if (atomic_xchg(&dpu_enc->frame_done_timeout_ms, 0)) { DPU_ERROR("enc%d timeout pending\n", drm_enc->base.id); - del_timer_sync(&dpu_enc->frame_done_timer); + timer_delete_sync(&dpu_enc->frame_done_timer); } dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_STOP); @@ -1619,7 +1585,7 @@ void dpu_encoder_frame_done_callback( if (!dpu_enc->frame_busy_mask[0]) { atomic_set(&dpu_enc->frame_done_timeout_ms, 0); - del_timer(&dpu_enc->frame_done_timer); + timer_delete(&dpu_enc->frame_done_timer); dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_FRAME_DONE); @@ -1654,6 +1620,7 @@ static void dpu_encoder_off_work(struct work_struct *work) static void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc, struct dpu_encoder_phys *phys, uint32_t extra_flush_bits) { + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); struct dpu_hw_ctl *ctl; int pending_kickoff_cnt; u32 ret = UINT_MAX; @@ -1671,6 +1638,15 @@ static void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc, pending_kickoff_cnt = dpu_encoder_phys_inc_pending(phys); + /* Return early if encoder is writeback and in clone mode */ + if (drm_enc->encoder_type == DRM_MODE_ENCODER_VIRTUAL && + dpu_enc->cwb_mask) { + DPU_DEBUG("encoder %d skip flush for concurrent writeback encoder\n", + DRMID(drm_enc)); + return; + } + + if (extra_flush_bits && ctl->ops.update_pending_flush) ctl->ops.update_pending_flush(ctl, extra_flush_bits); @@ -1693,6 +1669,8 @@ static void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc, */ static void _dpu_encoder_trigger_start(struct dpu_encoder_phys *phys) { + struct dpu_encoder_virt *dpu_enc; + if (!phys) { DPU_ERROR("invalid argument(s)\n"); return; @@ -1703,6 +1681,14 @@ static void _dpu_encoder_trigger_start(struct dpu_encoder_phys *phys) return; } + dpu_enc = to_dpu_encoder_virt(phys->parent); + + if (phys->parent->encoder_type == DRM_MODE_ENCODER_VIRTUAL && + dpu_enc->cwb_mask) { + DPU_DEBUG("encoder %d CWB enabled, skipping\n", DRMID(phys->parent)); + return; + } + if (phys->ops.trigger_start && phys->enable_state != DPU_ENC_DISABLED) phys->ops.trigger_start(phys); } @@ -2020,7 +2006,6 @@ static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_ctl *ctl, static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, struct drm_dsc_config *dsc) { - /* coding only for 2LM, 2enc, 1 dsc config */ struct dpu_encoder_phys *enc_master = dpu_enc->cur_master; struct dpu_hw_ctl *ctl = enc_master->hw_ctl; struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; @@ -2030,22 +2015,24 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, int dsc_common_mode; int pic_width; u32 initial_lines; + int num_dsc = 0; int i; for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { hw_pp[i] = dpu_enc->hw_pp[i]; hw_dsc[i] = dpu_enc->hw_dsc[i]; - if (!hw_pp[i] || !hw_dsc[i]) { - DPU_ERROR_ENC(dpu_enc, "invalid params for DSC\n"); - return; - } + if (!hw_pp[i] || !hw_dsc[i]) + break; + + num_dsc++; } - dsc_common_mode = 0; pic_width = dsc->pic_width; - dsc_common_mode = DSC_MODE_SPLIT_PANEL; + dsc_common_mode = 0; + if (num_dsc > 1) + dsc_common_mode |= DSC_MODE_SPLIT_PANEL; if (dpu_encoder_use_dsc_merge(enc_master->parent)) dsc_common_mode |= DSC_MODE_MULTIPLEX; if (enc_master->intf_mode == INTF_MODE_VIDEO) @@ -2054,14 +2041,10 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, this_frame_slices = pic_width / dsc->slice_width; intf_ip_w = this_frame_slices * dsc->slice_width; - /* - * dsc merge case: when using 2 encoders for the same stream, - * no. of slices need to be same on both the encoders. - */ - enc_ip_w = intf_ip_w / 2; + enc_ip_w = intf_ip_w / num_dsc; initial_lines = dpu_encoder_dsc_initial_line_calc(dsc, enc_ip_w); - for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) + for (i = 0; i < num_dsc; i++) dpu_encoder_dsc_pipe_cfg(ctl, hw_dsc[i], hw_pp[i], dsc, dsc_common_mode, initial_lines); } @@ -2135,6 +2118,25 @@ bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc) } /** + * dpu_encoder_start_frame_done_timer - Start the encoder frame done timer + * @drm_enc: Pointer to drm encoder structure + */ +void dpu_encoder_start_frame_done_timer(struct drm_encoder *drm_enc) +{ + struct dpu_encoder_virt *dpu_enc; + unsigned long timeout_ms; + + dpu_enc = to_dpu_encoder_virt(drm_enc); + timeout_ms = DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES * 1000 / + drm_mode_vrefresh(&drm_enc->crtc->state->adjusted_mode); + + atomic_set(&dpu_enc->frame_done_timeout_ms, timeout_ms); + mod_timer(&dpu_enc->frame_done_timer, + jiffies + msecs_to_jiffies(timeout_ms)); + +} + +/** * dpu_encoder_kickoff - trigger a double buffer flip of the ctl path * (i.e. ctl flush and start) immediately. * @drm_enc: encoder pointer @@ -2143,7 +2145,6 @@ void dpu_encoder_kickoff(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc; struct dpu_encoder_phys *phys; - unsigned long timeout_ms; unsigned int i; DPU_ATRACE_BEGIN("encoder_kickoff"); @@ -2151,13 +2152,6 @@ void dpu_encoder_kickoff(struct drm_encoder *drm_enc) trace_dpu_enc_kickoff(DRMID(drm_enc)); - timeout_ms = DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES * 1000 / - drm_mode_vrefresh(&drm_enc->crtc->state->adjusted_mode); - - atomic_set(&dpu_enc->frame_done_timeout_ms, timeout_ms); - mod_timer(&dpu_enc->frame_done_timer, - jiffies + msecs_to_jiffies(timeout_ms)); - /* All phys encs are ready to go, trigger the kickoff */ _dpu_encoder_kickoff_phys(dpu_enc); @@ -2173,32 +2167,41 @@ void dpu_encoder_kickoff(struct drm_encoder *drm_enc) static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc) { - struct dpu_hw_mixer_cfg mixer; int i, num_lm; struct dpu_global_state *global_state; - struct dpu_hw_blk *hw_lm[2]; - struct dpu_hw_mixer *hw_mixer[2]; + struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC]; + struct dpu_hw_mixer *hw_mixer[MAX_CHANNELS_PER_ENC]; struct dpu_hw_ctl *ctl = phys_enc->hw_ctl; - memset(&mixer, 0, sizeof(mixer)); - /* reset all mixers for this encoder */ - if (phys_enc->hw_ctl->ops.clear_all_blendstages) - phys_enc->hw_ctl->ops.clear_all_blendstages(phys_enc->hw_ctl); + if (ctl->ops.clear_all_blendstages) + ctl->ops.clear_all_blendstages(ctl); global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms); num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state, - phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm)); + phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm)); for (i = 0; i < num_lm; i++) { hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]); - if (phys_enc->hw_ctl->ops.update_pending_flush_mixer) - phys_enc->hw_ctl->ops.update_pending_flush_mixer(ctl, hw_mixer[i]->idx); + if (ctl->ops.update_pending_flush_mixer) + ctl->ops.update_pending_flush_mixer(ctl, hw_mixer[i]->idx); /* clear all blendstages */ - if (phys_enc->hw_ctl->ops.setup_blendstage) - phys_enc->hw_ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL); + if (ctl->ops.setup_blendstage) + ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL); + + if (hw_mixer[i]->ops.clear_all_blendstages) + hw_mixer[i]->ops.clear_all_blendstages(hw_mixer[i]); + + if (ctl->ops.set_active_lms) + ctl->ops.set_active_lms(ctl, NULL); + + if (ctl->ops.set_active_fetch_pipes) + ctl->ops.set_active_fetch_pipes(ctl, NULL); + + if (ctl->ops.set_active_pipes) + ctl->ops.set_active_pipes(ctl, NULL); } } @@ -2250,7 +2253,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) dpu_enc = to_dpu_encoder_virt(phys_enc->parent); - phys_enc->hw_ctl->ops.reset(ctl); + ctl->ops.reset(ctl); dpu_encoder_helper_reset_mixers(phys_enc); @@ -2265,8 +2268,8 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb, PINGPONG_NONE); /* mark WB flush as pending */ - if (phys_enc->hw_ctl->ops.update_pending_flush_wb) - phys_enc->hw_ctl->ops.update_pending_flush_wb(ctl, phys_enc->hw_wb->idx); + if (ctl->ops.update_pending_flush_wb) + ctl->ops.update_pending_flush_wb(ctl, phys_enc->hw_wb->idx); } else { for (i = 0; i < dpu_enc->num_phys_encs; i++) { if (dpu_enc->phys_encs[i] && phys_enc->hw_intf->ops.bind_pingpong_blk) @@ -2275,18 +2278,24 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) PINGPONG_NONE); /* mark INTF flush as pending */ - if (phys_enc->hw_ctl->ops.update_pending_flush_intf) - phys_enc->hw_ctl->ops.update_pending_flush_intf(phys_enc->hw_ctl, + if (ctl->ops.update_pending_flush_intf) + ctl->ops.update_pending_flush_intf(ctl, dpu_enc->phys_encs[i]->hw_intf->idx); } } + if (phys_enc->hw_pp && phys_enc->hw_pp->ops.setup_dither) + phys_enc->hw_pp->ops.setup_dither(phys_enc->hw_pp, NULL); + + if (dpu_enc->cwb_mask) + dpu_encoder_helper_phys_setup_cwb(phys_enc, false); + /* reset the merge 3D HW block */ 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) - phys_enc->hw_ctl->ops.update_pending_flush_merge_3d(ctl, + if (ctl->ops.update_pending_flush_merge_3d) + ctl->ops.update_pending_flush_merge_3d(ctl, phys_enc->hw_pp->merge_3d->idx); } @@ -2294,9 +2303,9 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) if (phys_enc->hw_cdm->ops.bind_pingpong_blk && phys_enc->hw_pp) phys_enc->hw_cdm->ops.bind_pingpong_blk(phys_enc->hw_cdm, PINGPONG_NONE); - if (phys_enc->hw_ctl->ops.update_pending_flush_cdm) - phys_enc->hw_ctl->ops.update_pending_flush_cdm(phys_enc->hw_ctl, - phys_enc->hw_cdm->idx); + if (ctl->ops.update_pending_flush_cdm) + ctl->ops.update_pending_flush_cdm(ctl, + phys_enc->hw_cdm->idx); } if (dpu_enc->dsc) { @@ -2307,6 +2316,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) intf_cfg.stream_sel = 0; /* Don't care value for video mode */ intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc); + intf_cfg.cwb = dpu_enc->cwb_mask; if (phys_enc->hw_intf) intf_cfg.intf = phys_enc->hw_intf->idx; @@ -2324,6 +2334,68 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) ctl->ops.clear_pending_flush(ctl); } +void dpu_encoder_helper_phys_setup_cwb(struct dpu_encoder_phys *phys_enc, + bool enable) +{ + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(phys_enc->parent); + struct dpu_hw_cwb *hw_cwb; + struct dpu_hw_ctl *hw_ctl; + struct dpu_hw_cwb_setup_cfg cwb_cfg; + + struct dpu_kms *dpu_kms; + struct dpu_global_state *global_state; + struct dpu_hw_blk *rt_pp_list[MAX_CHANNELS_PER_ENC]; + int num_pp; + + if (!phys_enc->hw_wb) + return; + + hw_ctl = phys_enc->hw_ctl; + + if (!phys_enc->hw_ctl) { + DPU_DEBUG("[wb:%d] no ctl assigned\n", + phys_enc->hw_wb->idx - WB_0); + return; + } + + dpu_kms = phys_enc->dpu_kms; + global_state = dpu_kms_get_existing_global_state(dpu_kms); + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, + phys_enc->parent->crtc, + DPU_HW_BLK_PINGPONG, rt_pp_list, + ARRAY_SIZE(rt_pp_list)); + + if (num_pp == 0 || num_pp > MAX_CHANNELS_PER_ENC) { + DPU_DEBUG_ENC(dpu_enc, "invalid num_pp %d\n", num_pp); + return; + } + + /* + * The CWB mux supports using LM or DSPP as tap points. For now, + * always use LM tap point + */ + cwb_cfg.input = INPUT_MODE_LM_OUT; + + for (int i = 0; i < MAX_CWB_PER_ENC; i++) { + hw_cwb = dpu_enc->hw_cwb[i]; + if (!hw_cwb) + continue; + + if (enable) { + struct dpu_hw_pingpong *hw_pp = + to_dpu_hw_pingpong(rt_pp_list[i]); + cwb_cfg.pp_idx = hw_pp->idx; + } else { + cwb_cfg.pp_idx = PINGPONG_NONE; + } + + hw_cwb->ops.config_cwb(hw_cwb, &cwb_cfg); + + if (hw_ctl->ops.update_pending_flush_cwb) + hw_ctl->ops.update_pending_flush_cwb(hw_ctl, hw_cwb->idx); + } +} + /** * dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block * @phys_enc: Pointer to physical encoder @@ -2510,6 +2582,38 @@ static int dpu_encoder_virt_add_phys_encs( return 0; } +/** + * dpu_encoder_get_clones - Calculate the possible_clones for DPU encoder + * @drm_enc: DRM encoder pointer + * Returns: possible_clones mask + */ +uint32_t dpu_encoder_get_clones(struct drm_encoder *drm_enc) +{ + struct drm_encoder *curr; + int type = drm_enc->encoder_type; + uint32_t clone_mask = drm_encoder_mask(drm_enc); + + /* + * Set writeback as possible clones of real-time DSI encoders and vice + * versa + * + * Writeback encoders can't be clones of each other and DSI + * encoders can't be clones of each other. + * + * TODO: Add DP encoders as valid possible clones for writeback encoders + * (and vice versa) once concurrent writeback has been validated for DP + */ + drm_for_each_encoder(curr, drm_enc->dev) { + if ((type == DRM_MODE_ENCODER_VIRTUAL && + curr->encoder_type == DRM_MODE_ENCODER_DSI) || + (type == DRM_MODE_ENCODER_DSI && + curr->encoder_type == DRM_MODE_ENCODER_VIRTUAL)) + clone_mask |= drm_encoder_mask(curr); + } + + return clone_mask; +} + static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, struct dpu_kms *dpu_kms, struct msm_display_info *disp_info) @@ -2594,8 +2698,8 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, static void dpu_encoder_frame_done_timeout(struct timer_list *t) { - struct dpu_encoder_virt *dpu_enc = from_timer(dpu_enc, t, - frame_done_timer); + struct dpu_encoder_virt *dpu_enc = timer_container_of(dpu_enc, t, + frame_done_timer); struct drm_encoder *drm_enc = &dpu_enc->base; u32 event; @@ -2627,7 +2731,6 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { .atomic_mode_set = dpu_encoder_virt_atomic_mode_set, .atomic_disable = dpu_encoder_virt_atomic_disable, .atomic_enable = dpu_encoder_virt_atomic_enable, - .atomic_check = dpu_encoder_virt_atomic_check, }; static const struct drm_encoder_funcs dpu_encoder_funcs = { @@ -2786,6 +2889,18 @@ enum dpu_intf_mode dpu_encoder_get_intf_mode(struct drm_encoder *encoder) } /** + * dpu_encoder_helper_get_cwb_mask - get CWB blocks mask for the DPU encoder + * @phys_enc: Pointer to physical encoder structure + */ +unsigned int dpu_encoder_helper_get_cwb_mask(struct dpu_encoder_phys *phys_enc) +{ + struct drm_encoder *encoder = phys_enc->parent; + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(encoder); + + return dpu_enc->cwb_mask; +} + +/** * dpu_encoder_helper_get_dsc - get DSC blocks mask for the DPU encoder * This helper function is used by physical encoder to get DSC blocks mask * used for this encoder. diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index 92b5ee390788..ca1ca2e51d7e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> @@ -60,6 +60,8 @@ enum dpu_intf_mode dpu_encoder_get_intf_mode(struct drm_encoder *encoder); void dpu_encoder_virt_runtime_resume(struct drm_encoder *encoder); +uint32_t dpu_encoder_get_clones(struct drm_encoder *drm_enc); + struct drm_encoder *dpu_encoder_init(struct drm_device *dev, int drm_enc_mode, struct msm_display_info *disp_info); @@ -80,6 +82,13 @@ int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos); bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc); +void dpu_encoder_update_topology(struct drm_encoder *drm_enc, + struct msm_display_topology *topology, + struct drm_atomic_state *state, + const struct drm_display_mode *adj_mode); + +bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state); + void dpu_encoder_prepare_wb_job(struct drm_encoder *drm_enc, struct drm_writeback_job *job); @@ -88,4 +97,5 @@ void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc, bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc); +void dpu_encoder_start_frame_done_timer(struct drm_encoder *drm_enc); #endif /* __DPU_ENCODER_H__ */ 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 63f09857025c..09395d7910ac 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. */ @@ -302,13 +302,15 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode( /* Use merge_3d unless DSC MERGE topology is used */ if (phys_enc->split_role == ENC_ROLE_SOLO && - dpu_cstate->num_mixers == CRTC_DUAL_MIXERS && + (dpu_cstate->num_mixers != 1) && !dpu_encoder_use_dsc_merge(phys_enc->parent)) return BLEND_3D_H_ROW_INT; return BLEND_3D_NONE; } +unsigned int dpu_encoder_helper_get_cwb_mask(struct dpu_encoder_phys *phys_enc); + unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc); struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc); @@ -331,6 +333,9 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc); +void dpu_encoder_helper_phys_setup_cwb(struct dpu_encoder_phys *phys_enc, + bool enable); + void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc, const struct msm_format *dpu_fmt, u32 output_type); 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 e9bbccc44dad..0ec6d67c7c70 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 @@ -5,6 +5,7 @@ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ #include <linux/delay.h> +#include <linux/string_choices.h> #include "dpu_encoder_phys.h" #include "dpu_hw_interrupts.h" #include "dpu_hw_pingpong.h" @@ -59,6 +60,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg( return; intf_cfg.intf = phys_enc->hw_intf->idx; + if (phys_enc->split_role == ENC_ROLE_MASTER) + intf_cfg.intf_master = phys_enc->hw_intf->idx; intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD; intf_cfg.stream_sel = cmd_enc->stream_sel; intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); @@ -66,7 +69,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg( ctl->ops.setup_intf_cfg(ctl, &intf_cfg); /* setup which pp blk will connect to this intf */ - if (test_bit(DPU_CTL_ACTIVE_CFG, &ctl->caps->features) && phys_enc->hw_intf->ops.bind_pingpong_blk) + if (phys_enc->dpu_kms->catalog->mdss_ver->core_major_ver >= 5 && + phys_enc->hw_intf->ops.bind_pingpong_blk) phys_enc->hw_intf->ops.bind_pingpong_blk( phys_enc->hw_intf, phys_enc->hw_pp->idx); @@ -261,7 +265,7 @@ static int dpu_encoder_phys_cmd_control_vblank_irq( DRM_DEBUG_KMS("id:%u pp:%d enable=%s/%d\n", DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, - enable ? "true" : "false", refcount); + str_true_false(enable), refcount); if (enable) { if (phys_enc->vblank_refcount == 0) @@ -285,7 +289,7 @@ end: DRM_ERROR("vblank irq err id:%u pp:%d ret:%d, enable %s/%d\n", DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, ret, - enable ? "true" : "false", refcount); + str_true_false(enable), refcount); } return ret; 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 abd6600046cb..0ba777bda253 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 @@ -94,17 +94,21 @@ static void drm_mode_to_intf_timing_params( timing->vsync_polarity = 0; } - /* for DP/EDP, Shift timings to align it to bottom right */ - if (phys_enc->hw_intf->cap->type == INTF_DP) { + timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent); + timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent); + + /* + * For DP/EDP, Shift timings to align it to bottom right. + * wide_bus_en is set for everything excluding SDM845 & + * porch changes cause DisplayPort failure and HDMI tearing. + */ + if (phys_enc->hw_intf->cap->type == INTF_DP && timing->wide_bus_en) { timing->h_back_porch += timing->h_front_porch; timing->h_front_porch = 0; timing->v_back_porch += timing->v_front_porch; timing->v_front_porch = 0; } - timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent); - timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent); - /* * for DP, divide the horizonal parameters by 2 when * widebus is enabled @@ -298,6 +302,8 @@ static void dpu_encoder_phys_vid_setup_timing_engine( if (phys_enc->hw_cdm) intf_cfg.cdm = phys_enc->hw_cdm->idx; intf_cfg.intf = phys_enc->hw_intf->idx; + if (phys_enc->split_role == ENC_ROLE_MASTER) + intf_cfg.intf_master = phys_enc->hw_intf->idx; intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_VID; intf_cfg.stream_sel = 0; /* Don't care value for video mode */ intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); @@ -307,8 +313,7 @@ static void dpu_encoder_phys_vid_setup_timing_engine( spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); phys_enc->hw_intf->ops.setup_timing_gen(phys_enc->hw_intf, - &timing_params, fmt, - phys_enc->dpu_kms->catalog->mdss_ver); + &timing_params, fmt); phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg); /* setup which pp blk will connect to this intf */ @@ -372,7 +377,8 @@ static void dpu_encoder_phys_vid_underrun_irq(void *arg) static bool dpu_encoder_phys_vid_needs_single_flush( struct dpu_encoder_phys *phys_enc) { - return phys_enc->split_role != ENC_ROLE_SOLO; + return !(phys_enc->dpu_kms->catalog->mdss_ver->core_major_ver >= 5) && + phys_enc->split_role != ENC_ROLE_SOLO; } static void dpu_encoder_phys_vid_atomic_mode_set( 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 4c006ec74575..46f348972a97 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 @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ @@ -68,7 +68,7 @@ static void dpu_encoder_phys_wb_set_ot_limit( ot_params.num = hw_wb->idx - WB_0; ot_params.width = phys_enc->cached_mode.hdisplay; ot_params.height = phys_enc->cached_mode.vdisplay; - ot_params.is_wfd = true; + ot_params.is_wfd = !dpu_encoder_helper_get_cwb_mask(phys_enc); ot_params.frame_rate = drm_mode_vrefresh(&phys_enc->cached_mode); ot_params.vbif_idx = hw_wb->caps->vbif_idx; ot_params.rd = false; @@ -111,7 +111,7 @@ static void dpu_encoder_phys_wb_set_qos_remap( qos_params.vbif_idx = hw_wb->caps->vbif_idx; qos_params.xin_id = hw_wb->caps->xin_id; qos_params.num = hw_wb->idx - WB_0; - qos_params.is_rt = false; + qos_params.is_rt = dpu_encoder_helper_get_cwb_mask(phys_enc); DPU_DEBUG("[qos_remap] wb:%d vbif:%d xin:%d is_rt:%d\n", qos_params.num, @@ -174,6 +174,7 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc, struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); struct dpu_hw_wb *hw_wb; struct dpu_hw_wb_cfg *wb_cfg; + u32 cdp_usage; if (!phys_enc || !phys_enc->dpu_kms || !phys_enc->dpu_kms->catalog) { DPU_ERROR("invalid encoder\n"); @@ -182,6 +183,10 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc, hw_wb = phys_enc->hw_wb; wb_cfg = &wb_enc->wb_cfg; + if (dpu_encoder_helper_get_cwb_mask(phys_enc)) + cdp_usage = DPU_PERF_CDP_USAGE_RT; + else + cdp_usage = DPU_PERF_CDP_USAGE_NRT; wb_cfg->intf_mode = phys_enc->intf_mode; wb_cfg->roi.x1 = 0; @@ -199,7 +204,7 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc, const struct dpu_perf_cfg *perf = phys_enc->dpu_kms->catalog->perf; hw_wb->ops.setup_cdp(hw_wb, format, - perf->cdp_cfg[DPU_PERF_CDP_USAGE_NRT].wr_enable); + perf->cdp_cfg[cdp_usage].wr_enable); } if (hw_wb->ops.setup_outaddress) @@ -213,7 +218,6 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc, static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc) { struct dpu_hw_wb *hw_wb; - struct dpu_hw_ctl *ctl; struct dpu_hw_cdm *hw_cdm; if (!phys_enc) { @@ -222,10 +226,9 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc) } hw_wb = phys_enc->hw_wb; - ctl = phys_enc->hw_ctl; hw_cdm = phys_enc->hw_cdm; - if (test_bit(DPU_CTL_ACTIVE_CFG, &ctl->caps->features) && + if (phys_enc->dpu_kms->catalog->mdss_ver->core_major_ver >= 5 && (phys_enc->hw_ctl && phys_enc->hw_ctl->ops.setup_intf_cfg)) { struct dpu_hw_intf_cfg intf_cfg = {0}; @@ -236,6 +239,7 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc) intf_cfg.intf = DPU_NONE; intf_cfg.wb = hw_wb->idx; + intf_cfg.cwb = dpu_encoder_helper_get_cwb_mask(phys_enc); if (mode_3d && hw_pp && hw_pp->merge_3d) intf_cfg.merge_3d = hw_pp->merge_3d->idx; @@ -340,6 +344,8 @@ static void dpu_encoder_phys_wb_setup( dpu_encoder_helper_phys_setup_cdm(phys_enc, format, CDM_CDWN_OUTPUT_WB); + dpu_encoder_helper_phys_setup_cwb(phys_enc, true); + dpu_encoder_phys_wb_setup_ctl(phys_enc); } @@ -440,7 +446,7 @@ static void _dpu_encoder_phys_wb_handle_wbdone_timeout( static int dpu_encoder_phys_wb_wait_for_commit_done( struct dpu_encoder_phys *phys_enc) { - unsigned long ret; + int ret; struct dpu_encoder_wait_info wait_info; struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); @@ -526,7 +532,6 @@ static void dpu_encoder_phys_wb_enable(struct dpu_encoder_phys *phys_enc) static void dpu_encoder_phys_wb_disable(struct dpu_encoder_phys *phys_enc) { struct dpu_hw_wb *hw_wb = phys_enc->hw_wb; - struct dpu_hw_ctl *hw_ctl = phys_enc->hw_ctl; DPU_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0); @@ -548,7 +553,7 @@ static void dpu_encoder_phys_wb_disable(struct dpu_encoder_phys *phys_enc) * WB support is added to those targets will need to add * the legacy teardown sequence as well. */ - if (hw_ctl->caps->features & BIT(DPU_CTL_ACTIVE_CFG)) + if (phys_enc->dpu_kms->catalog->mdss_ver->core_major_ver >= 5) dpu_encoder_helper_phys_cleanup(phys_enc); phys_enc->enable_state = DPU_ENC_DISABLED; @@ -558,7 +563,6 @@ static void dpu_encoder_phys_wb_prepare_wb_job(struct dpu_encoder_phys *phys_enc struct drm_writeback_job *job) { const struct msm_format *format; - struct msm_gem_address_space *aspace; struct dpu_hw_wb_cfg *wb_cfg; int ret; struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); @@ -568,13 +572,12 @@ static void dpu_encoder_phys_wb_prepare_wb_job(struct dpu_encoder_phys *phys_enc wb_enc->wb_job = job; wb_enc->wb_conn = job->connector; - aspace = phys_enc->dpu_kms->base.aspace; wb_cfg = &wb_enc->wb_cfg; memset(wb_cfg, 0, sizeof(struct dpu_hw_wb_cfg)); - ret = msm_framebuffer_prepare(job->fb, aspace, false); + ret = msm_framebuffer_prepare(job->fb, false); if (ret) { DPU_ERROR("prep fb failed, %d\n", ret); return; @@ -588,7 +591,7 @@ static void dpu_encoder_phys_wb_prepare_wb_job(struct dpu_encoder_phys *phys_enc return; } - dpu_format_populate_addrs(aspace, job->fb, &wb_cfg->dest); + dpu_format_populate_addrs(job->fb, &wb_cfg->dest); wb_cfg->dest.width = job->fb->width; wb_cfg->dest.height = job->fb->height; @@ -611,14 +614,11 @@ static void dpu_encoder_phys_wb_cleanup_wb_job(struct dpu_encoder_phys *phys_enc struct drm_writeback_job *job) { struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); - struct msm_gem_address_space *aspace; if (!job->fb) return; - aspace = phys_enc->dpu_kms->base.aspace; - - msm_framebuffer_cleanup(job->fb, aspace, false); + msm_framebuffer_cleanup(job->fb, false); wb_enc->wb_job = NULL; wb_enc->wb_conn = NULL; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c index 59c9427da7dd..b0d585c5315c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c @@ -274,15 +274,14 @@ int dpu_format_populate_plane_sizes( return _dpu_format_populate_plane_sizes_linear(fmt, fb, layout); } -static void _dpu_format_populate_addrs_ubwc(struct msm_gem_address_space *aspace, - struct drm_framebuffer *fb, +static void _dpu_format_populate_addrs_ubwc(struct drm_framebuffer *fb, struct dpu_hw_fmt_layout *layout) { const struct msm_format *fmt; uint32_t base_addr = 0; bool meta; - base_addr = msm_framebuffer_iova(fb, aspace, 0); + base_addr = msm_framebuffer_iova(fb, 0); fmt = msm_framebuffer_format(fb); meta = MSM_FORMAT_IS_UBWC(fmt); @@ -355,26 +354,23 @@ static void _dpu_format_populate_addrs_ubwc(struct msm_gem_address_space *aspace } } -static void _dpu_format_populate_addrs_linear(struct msm_gem_address_space *aspace, - struct drm_framebuffer *fb, +static void _dpu_format_populate_addrs_linear(struct drm_framebuffer *fb, struct dpu_hw_fmt_layout *layout) { unsigned int i; /* Populate addresses for simple formats here */ for (i = 0; i < layout->num_planes; ++i) - layout->plane_addr[i] = msm_framebuffer_iova(fb, aspace, i); -} + layout->plane_addr[i] = msm_framebuffer_iova(fb, i); + } /** * dpu_format_populate_addrs - populate buffer addresses based on * mmu, fb, and format found in the fb - * @aspace: address space pointer * @fb: framebuffer pointer * @layout: format layout structure to populate */ -void dpu_format_populate_addrs(struct msm_gem_address_space *aspace, - struct drm_framebuffer *fb, +void dpu_format_populate_addrs(struct drm_framebuffer *fb, struct dpu_hw_fmt_layout *layout) { const struct msm_format *fmt; @@ -384,7 +380,7 @@ void dpu_format_populate_addrs(struct msm_gem_address_space *aspace, /* Populate the addresses given the fb */ if (MSM_FORMAT_IS_UBWC(fmt) || MSM_FORMAT_IS_TILE(fmt)) - _dpu_format_populate_addrs_ubwc(aspace, fb, layout); + _dpu_format_populate_addrs_ubwc(fb, layout); else - _dpu_format_populate_addrs_linear(aspace, fb, layout); + _dpu_format_populate_addrs_linear(fb, layout); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h index c6145d43aa3f..dc03f522e616 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h @@ -31,8 +31,7 @@ static inline bool dpu_find_format(u32 format, const u32 *supported_formats, return false; } -void dpu_format_populate_addrs(struct msm_gem_address_space *aspace, - struct drm_framebuffer *fb, +void dpu_format_populate_addrs(struct drm_framebuffer *fb, struct dpu_hw_fmt_layout *layout); int dpu_format_populate_plane_sizes( 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 2cbf41f33cc0..23bb39b471b7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -34,13 +34,13 @@ #define VIG_MSM8998_MASK \ (VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3_COMPATIBLE)) -#define VIG_SDM845_MASK \ - (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3_COMPATIBLE)) +#define VIG_SDM845_MASK_NO_SDMA \ + (VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3_COMPATIBLE)) #define VIG_SDM845_MASK_SDMA \ - (VIG_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2)) + (VIG_SDM845_MASK_NO_SDMA | BIT(DPU_SSPP_SMART_DMA_V2)) -#define VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL)) +#define VIG_QCM2290_MASK (VIG_BASE_MASK) #define DMA_MSM8953_MASK \ (BIT(DPU_SSPP_QOS)) @@ -54,24 +54,24 @@ BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT)) #define VIG_SC7280_MASK \ - (VIG_SDM845_MASK | BIT(DPU_SSPP_INLINE_ROTATION)) + (VIG_SDM845_MASK_NO_SDMA | BIT(DPU_SSPP_INLINE_ROTATION)) #define VIG_SC7280_MASK_SDMA \ (VIG_SC7280_MASK | BIT(DPU_SSPP_SMART_DMA_V2)) -#define DMA_SDM845_MASK \ - (BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\ +#define DMA_SDM845_MASK_NO_SDMA \ + (BIT(DPU_SSPP_QOS) | \ BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\ BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT)) -#define DMA_CURSOR_SDM845_MASK \ - (DMA_SDM845_MASK | BIT(DPU_SSPP_CURSOR)) +#define DMA_CURSOR_SDM845_MASK_NO_SDMA \ + (DMA_SDM845_MASK_NO_SDMA | BIT(DPU_SSPP_CURSOR)) #define DMA_SDM845_MASK_SDMA \ - (DMA_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2)) + (DMA_SDM845_MASK_NO_SDMA | BIT(DPU_SSPP_SMART_DMA_V2)) #define DMA_CURSOR_SDM845_MASK_SDMA \ - (DMA_CURSOR_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2)) + (DMA_CURSOR_SDM845_MASK_NO_SDMA | BIT(DPU_SSPP_SMART_DMA_V2)) #define DMA_CURSOR_MSM8996_MASK \ (DMA_MSM8996_MASK | BIT(DPU_SSPP_CURSOR)) @@ -89,45 +89,6 @@ #define MIXER_MSM8998_MASK \ (BIT(DPU_MIXER_SOURCESPLIT)) -#define MIXER_SDM845_MASK \ - (BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA)) - -#define MIXER_QCM2290_MASK \ - (BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA)) - -#define PINGPONG_MSM8996_MASK \ - (BIT(DPU_PINGPONG_DSC)) - -#define PINGPONG_MSM8996_TE2_MASK \ - (PINGPONG_MSM8996_MASK | BIT(DPU_PINGPONG_TE2)) - -#define PINGPONG_SDM845_MASK \ - (BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_DSC)) - -#define PINGPONG_SDM845_TE2_MASK \ - (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2)) - -#define PINGPONG_SM8150_MASK \ - (BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_DSC)) - -#define CTL_SC7280_MASK \ - (BIT(DPU_CTL_ACTIVE_CFG) | \ - BIT(DPU_CTL_FETCH_ACTIVE) | \ - BIT(DPU_CTL_VM_CFG) | \ - BIT(DPU_CTL_DSPP_SUB_BLOCK_FLUSH)) - -#define CTL_SM8550_MASK \ - (CTL_SC7280_MASK | BIT(DPU_CTL_HAS_LAYER_EXT4)) - -#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC) - -#define INTF_SC7180_MASK \ - (BIT(DPU_INTF_INPUT_CTRL) | \ - BIT(DPU_INTF_STATUS_SUPPORTED) | \ - BIT(DPU_DATA_HCTL_EN)) - -#define INTF_SC7280_MASK (INTF_SC7180_MASK) - #define WB_SDM845_MASK (BIT(DPU_WB_LINE_MODE) | \ BIT(DPU_WB_UBWC) | \ BIT(DPU_WB_YUV_CONFIG) | \ @@ -137,9 +98,6 @@ BIT(DPU_WB_QOS_8LVL) | \ BIT(DPU_WB_CDP)) -#define WB_SM8250_MASK (WB_SDM845_MASK | \ - BIT(DPU_WB_INPUT_CTRL)) - #define DEFAULT_PIXEL_RAM_SIZE (50 * 1024) #define DEFAULT_DPU_LINE_WIDTH 2048 #define DEFAULT_DPU_OUTPUT_LINE_WIDTH 2560 @@ -232,37 +190,6 @@ static const u32 rotation_v2_formats[] = { /* TODO add formats after validation */ }; -static const u32 wb2_formats_rgb[] = { - DRM_FORMAT_RGB565, - DRM_FORMAT_BGR565, - DRM_FORMAT_RGB888, - DRM_FORMAT_ARGB8888, - DRM_FORMAT_RGBA8888, - DRM_FORMAT_ABGR8888, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGBX8888, - DRM_FORMAT_XBGR8888, - DRM_FORMAT_ARGB1555, - DRM_FORMAT_RGBA5551, - DRM_FORMAT_XRGB1555, - DRM_FORMAT_RGBX5551, - DRM_FORMAT_ARGB4444, - DRM_FORMAT_RGBA4444, - DRM_FORMAT_RGBX4444, - DRM_FORMAT_XRGB4444, - DRM_FORMAT_BGR888, - DRM_FORMAT_BGRA8888, - DRM_FORMAT_BGRX8888, - DRM_FORMAT_ABGR1555, - DRM_FORMAT_BGRA5551, - DRM_FORMAT_XBGR1555, - DRM_FORMAT_BGRX5551, - DRM_FORMAT_ABGR4444, - DRM_FORMAT_BGRA4444, - DRM_FORMAT_BGRX4444, - DRM_FORMAT_XBGR4444, -}; - static const u32 wb2_formats_rgb_yuv[] = { DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, @@ -340,8 +267,8 @@ static const u32 wb2_formats_rgb_yuv[] = { .base = 0x200, .len = 0xa0,}, \ .csc_blk = {.name = "csc", \ .base = 0x320, .len = 0x100,}, \ - .format_list = plane_formats_yuv, \ - .num_formats = ARRAY_SIZE(plane_formats_yuv), \ + .format_list = plane_formats, \ + .num_formats = ARRAY_SIZE(plane_formats), \ .rotation_cfg = NULL, \ } @@ -399,6 +326,9 @@ static const struct dpu_sspp_sub_blks dpu_vig_sblk_qseed3_3_2 = static const struct dpu_sspp_sub_blks dpu_vig_sblk_qseed3_3_3 = _VIG_SBLK(SSPP_SCALER_VER(3, 3)); +static const struct dpu_sspp_sub_blks dpu_vig_sblk_qseed3_3_4 = + _VIG_SBLK(SSPP_SCALER_VER(3, 4)); + static const struct dpu_sspp_sub_blks dpu_rgb_sblk = _RGB_SBLK(); static const struct dpu_sspp_sub_blks dpu_dma_sblk = _DMA_SBLK(); @@ -407,10 +337,7 @@ static const struct dpu_sspp_sub_blks dpu_dma_sblk = _DMA_SBLK(); * MIXER sub blocks config *************************************************************/ -/* MSM8998 */ - static const struct dpu_lm_sub_blks msm8998_lm_sblk = { - .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .maxblendstages = 7, /* excluding base layer */ .blendstage_base = { /* offsets relative to mixer base */ 0x20, 0x50, 0x80, 0xb0, 0x230, @@ -418,10 +345,7 @@ static const struct dpu_lm_sub_blks msm8998_lm_sblk = { }, }; -/* SDM845 */ - static const struct dpu_lm_sub_blks sdm845_lm_sblk = { - .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .maxblendstages = 11, /* excluding base layer */ .blendstage_base = { /* offsets relative to mixer base */ 0x20, 0x38, 0x50, 0x68, 0x80, 0x98, @@ -429,20 +353,23 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = { }, }; -/* SC7180 */ - static const struct dpu_lm_sub_blks sc7180_lm_sblk = { - .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .maxblendstages = 7, /* excluding base layer */ .blendstage_base = { /* offsets relative to mixer base */ 0x20, 0x38, 0x50, 0x68, 0x80, 0x98, 0xb0 }, }; -/* QCM2290 */ +static const struct dpu_lm_sub_blks sm8750_lm_sblk = { + .maxblendstages = 11, /* excluding base layer */ + .blendstage_base = { /* offsets relative to mixer base */ + /* 0x40 + n*0x30 */ + 0x40, 0x70, 0xa0, 0xd0, 0x100, 0x130, 0x160, 0x190, 0x1c0, + 0x1f0, 0x220 + }, +}; static const struct dpu_lm_sub_blks qcm2290_lm_sblk = { - .maxwidth = DEFAULT_DPU_LINE_WIDTH, .maxblendstages = 4, /* excluding base layer */ .blendstage_base = { /* offsets relative to mixer base */ 0x20, 0x38, 0x50, 0x68 @@ -462,25 +389,19 @@ static const struct dpu_dspp_sub_blks sdm845_dspp_sblk = { .len = 0x90, .version = 0x40000}, }; +static const struct dpu_dspp_sub_blks sm8750_dspp_sblk = { + .pcc = {.name = "pcc", .base = 0x1700, + .len = 0x90, .version = 0x60000}, +}; + /************************************************************* * PINGPONG sub blocks config *************************************************************/ -static const struct dpu_pingpong_sub_blks msm8996_pp_sblk_te = { - .te2 = {.name = "te2", .base = 0x2000, .len = 0x0, - .version = 0x1}, -}; static const struct dpu_pingpong_sub_blks msm8996_pp_sblk = { /* No dither block */ }; -static const struct dpu_pingpong_sub_blks sdm845_pp_sblk_te = { - .te2 = {.name = "te2", .base = 0x2000, .len = 0x0, - .version = 0x1}, - .dither = {.name = "dither", .base = 0x30e0, - .len = 0x20, .version = 0x10000}, -}; - static const struct dpu_pingpong_sub_blks sdm845_pp_sblk = { .dither = {.name = "dither", .base = 0x30e0, .len = 0x20, .version = 0x10000}, @@ -504,10 +425,27 @@ static const struct dpu_dsc_sub_blks dsc_sblk_1 = { .ctl = {.name = "ctl", .base = 0xF80, .len = 0x10}, }; +static const struct dpu_dsc_sub_blks sm8750_dsc_sblk_0 = { + .enc = {.name = "enc", .base = 0x100, .len = 0x100}, + .ctl = {.name = "ctl", .base = 0xF00, .len = 0x24}, +}; + +static const struct dpu_dsc_sub_blks sm8750_dsc_sblk_1 = { + .enc = {.name = "enc", .base = 0x200, .len = 0x100}, + .ctl = {.name = "ctl", .base = 0xF80, .len = 0x24}, +}; + /************************************************************* * CDM block config *************************************************************/ -static const struct dpu_cdm_cfg sc7280_cdm = { +static const struct dpu_cdm_cfg dpu_cdm_1_x_4_x = { + .name = "cdm_0", + .id = CDM_0, + .len = 0x224, + .base = 0x79200, +}; + +static const struct dpu_cdm_cfg dpu_cdm_5_x = { .name = "cdm_0", .id = CDM_0, .len = 0x228, @@ -765,6 +703,7 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = { #include "catalog/dpu_5_0_sm8150.h" #include "catalog/dpu_5_1_sc8180x.h" #include "catalog/dpu_5_2_sm7150.h" +#include "catalog/dpu_5_3_sm6150.h" #include "catalog/dpu_5_4_sm6125.h" #include "catalog/dpu_6_0_sm8250.h" @@ -782,7 +721,9 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = { #include "catalog/dpu_8_4_sa8775p.h" #include "catalog/dpu_9_0_sm8550.h" - +#include "catalog/dpu_9_1_sar2130p.h" #include "catalog/dpu_9_2_x1e80100.h" #include "catalog/dpu_10_0_sm8650.h" +#include "catalog/dpu_12_0_sm8750.h" +#include "catalog/dpu_12_2_glymur.h" 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 c701d18c3522..336757103b5a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -24,31 +24,11 @@ #define DPU_MAX_IMG_WIDTH 0x3fff #define DPU_MAX_IMG_HEIGHT 0x3fff -#define CRTC_DUAL_MIXERS 2 +#define CRTC_QUAD_MIXERS 4 #define MAX_XIN_COUNT 16 /** - * MDP TOP BLOCK features - * @DPU_MDP_PANIC_PER_PIPE Panic configuration needs to be done per pipe - * @DPU_MDP_10BIT_SUPPORT, Chipset supports 10 bit pixel formats - * @DPU_MDP_PERIPH_0_REMOVED Indicates that access to periph top0 block results - * in a failure - * @DPU_MDP_VSYNC_SEL Enables vsync source selection via MDP_VSYNC_SEL register - * (moved into INTF block since DPU 5.0.0) - * @DPU_MDP_MAX Maximum value - - */ -enum { - DPU_MDP_PANIC_PER_PIPE = 0x1, - DPU_MDP_10BIT_SUPPORT, - DPU_MDP_AUDIO_SELECT, - DPU_MDP_PERIPH_0_REMOVED, - DPU_MDP_VSYNC_SEL, - DPU_MDP_MAX -}; - -/** * SSPP sub-blocks/features * @DPU_SSPP_SCALER_QSEED2, QSEED2 algorithm support * @DPU_SSPP_SCALER_QSEED3_COMPATIBLE, QSEED3-compatible alogorithm support (includes QSEED3, QSEED3LITE and QSEED4) @@ -57,7 +37,6 @@ enum { * @DPU_SSPP_CSC_10BIT, Support of 10-bit Color space conversion * @DPU_SSPP_CURSOR, SSPP can be used as a cursor layer * @DPU_SSPP_QOS, SSPP support QoS control, danger/safe/creq - * @DPU_SSPP_QOS_8LVL, SSPP support 8-level QoS control * @DPU_SSPP_EXCL_RECT, SSPP supports exclusion rect * @DPU_SSPP_SMART_DMA_V1, SmartDMA 1.0 support * @DPU_SSPP_SMART_DMA_V2, SmartDMA 2.0 support @@ -75,7 +54,6 @@ enum { DPU_SSPP_CSC_10BIT, DPU_SSPP_CURSOR, DPU_SSPP_QOS, - DPU_SSPP_QOS_8LVL, DPU_SSPP_EXCL_RECT, DPU_SSPP_SMART_DMA_V1, DPU_SSPP_SMART_DMA_V2, @@ -88,20 +66,12 @@ enum { /* * MIXER sub-blocks/features - * @DPU_MIXER_LAYER Layer mixer layer blend configuration, * @DPU_MIXER_SOURCESPLIT Layer mixer supports source-split configuration - * @DPU_MIXER_GC Gamma correction block - * @DPU_DIM_LAYER Layer mixer supports dim layer - * @DPU_MIXER_COMBINED_ALPHA Layer mixer has combined alpha register * @DPU_MIXER_MAX maximum value */ enum { - DPU_MIXER_LAYER = 0x1, - DPU_MIXER_SOURCESPLIT, - DPU_MIXER_GC, - DPU_DIM_LAYER, - DPU_MIXER_COMBINED_ALPHA, - DPU_MIXER_MAX + DPU_MIXER_SOURCESPLIT = 0x1, + DPU_MIXER_MAX, }; /** @@ -114,59 +84,16 @@ enum { }; /** - * PINGPONG sub-blocks - * @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 - * @DPU_PINGPONG_DITHER Dither blocks - * @DPU_PINGPONG_DSC PP block supports DSC - * @DPU_PINGPONG_MAX - */ -enum { - DPU_PINGPONG_TE2 = 0x1, - DPU_PINGPONG_SPLIT, - DPU_PINGPONG_SLAVE, - DPU_PINGPONG_DITHER, - DPU_PINGPONG_DSC, - DPU_PINGPONG_MAX -}; - -/** * CTL sub-blocks * @DPU_CTL_SPLIT_DISPLAY: CTL supports video mode split display - * @DPU_CTL_FETCH_ACTIVE: Active CTL for fetch HW (SSPPs) - * @DPU_CTL_VM_CFG: CTL config to support multiple VMs - * @DPU_CTL_HAS_LAYER_EXT4: CTL has the CTL_LAYER_EXT4 register - * @DPU_CTL_DSPP_BLOCK_FLUSH: CTL config to support dspp sub-block flush * @DPU_CTL_MAX */ enum { DPU_CTL_SPLIT_DISPLAY = 0x1, - DPU_CTL_ACTIVE_CFG, - DPU_CTL_FETCH_ACTIVE, - DPU_CTL_VM_CFG, - DPU_CTL_HAS_LAYER_EXT4, - DPU_CTL_DSPP_SUB_BLOCK_FLUSH, DPU_CTL_MAX }; /** - * INTF sub-blocks - * @DPU_INTF_INPUT_CTRL Supports the setting of pp block from which - * pixel data arrives to this INTF - * @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 - * @DPU_INTF_MAX - */ -enum { - DPU_INTF_INPUT_CTRL = 0x1, - DPU_DATA_HCTL_EN, - DPU_INTF_STATUS_SUPPORTED, - DPU_INTF_MAX -}; - -/** * WB sub-blocks and features * @DPU_WB_LINE_MODE Writeback module supports line/linear mode * @DPU_WB_BLOCK_MODE Writeback module supports block mode read @@ -182,8 +109,6 @@ enum { * @DPU_WB_QOS, Writeback supports QoS control, danger/safe/creq * @DPU_WB_QOS_8LVL, Writeback supports 8-level QoS control * @DPU_WB_CDP Writeback supports client driven prefetch - * @DPU_WB_INPUT_CTRL Writeback supports from which pp block input pixel - * data arrives. * @DPU_WB_CROP CWB supports cropping * @DPU_WB_MAX maximum value */ @@ -197,7 +122,6 @@ enum { DPU_WB_QOS, DPU_WB_QOS_8LVL, DPU_WB_CDP, - DPU_WB_INPUT_CTRL, DPU_WB_CROP, DPU_WB_MAX }; @@ -216,16 +140,11 @@ enum { /** * DSC sub-blocks/features - * @DPU_DSC_OUTPUT_CTRL Configure which PINGPONG block gets - * the pixel output from this DSC. - * @DPU_DSC_HW_REV_1_2 DSC block supports DSC 1.1 and 1.2 * @DPU_DSC_NATIVE_42x_EN Supports NATIVE_422_EN and NATIVE_420_EN encoding * @DPU_DSC_MAX */ enum { - DPU_DSC_OUTPUT_CTRL = 0x1, - DPU_DSC_HW_REV_1_2, - DPU_DSC_NATIVE_42x_EN, + DPU_DSC_NATIVE_42x_EN = 0x1, DPU_DSC_MAX }; @@ -235,14 +154,12 @@ enum { * @id: enum identifying this block * @base: register base offset to mdss * @len: length of hardware block - * @features bit mask identifying sub-blocks/features */ #define DPU_HW_BLK_INFO \ char name[DPU_HW_BLK_NAME_LEN]; \ u32 id; \ u32 base; \ - u32 len; \ - unsigned long features + u32 len /** * struct dpu_scaler_blk: Scaler information @@ -390,7 +307,6 @@ struct dpu_sspp_sub_blks { * @blendstage_base: Blend-stage register base offset */ struct dpu_lm_sub_blks { - u32 maxwidth; u32 maxblendstages; u32 blendstage_base[MAX_BLOCKS]; }; @@ -404,8 +320,6 @@ struct dpu_dspp_sub_blks { }; struct dpu_pingpong_sub_blks { - struct dpu_pp_blk te; - struct dpu_pp_blk te2; struct dpu_pp_blk dither; }; @@ -459,7 +373,6 @@ struct dpu_clk_ctrl_reg { /* struct dpu_mdp_cfg : MDP TOP-BLK instance info * @id: index identifying this block * @base: register base offset to mdss - * @features bit mask identifying sub-blocks/features * @clk_ctrls clock control register definition */ struct dpu_mdp_cfg { @@ -475,6 +388,7 @@ struct dpu_mdp_cfg { */ struct dpu_ctl_cfg { DPU_HW_BLK_INFO; + unsigned long features; unsigned int intr_start; }; @@ -490,6 +404,7 @@ struct dpu_ctl_cfg { */ struct dpu_sspp_cfg { DPU_HW_BLK_INFO; + unsigned long features; const struct dpu_sspp_sub_blks *sblk; u32 xin_id; enum dpu_clk_ctrl_type clk_ctrl; @@ -507,6 +422,7 @@ struct dpu_sspp_cfg { */ struct dpu_lm_cfg { DPU_HW_BLK_INFO; + unsigned long features; const struct dpu_lm_sub_blks *sblk; u32 pingpong; u32 dspp; @@ -517,7 +433,6 @@ struct dpu_lm_cfg { * struct dpu_dspp_cfg - information of DSPP blocks * @id enum identifying this block * @base register offset of this block - * @features bit mask identifying sub-blocks/features * supported by this block * @sblk sub-blocks information */ @@ -530,7 +445,6 @@ struct dpu_dspp_cfg { * struct dpu_pingpong_cfg - information of PING-PONG blocks * @id enum identifying this block * @base register offset of this block - * @features bit mask identifying sub-blocks/features * @intr_done: index for PINGPONG done interrupt * @intr_rdptr: index for PINGPONG readpointer done interrupt * @sblk sub-blocks information @@ -547,8 +461,6 @@ struct dpu_pingpong_cfg { * struct dpu_merge_3d_cfg - information of DSPP blocks * @id enum identifying this block * @base register offset of this block - * @features bit mask identifying sub-blocks/features - * supported by this block * @sblk sub-blocks information */ struct dpu_merge_3d_cfg { @@ -566,6 +478,7 @@ struct dpu_merge_3d_cfg { */ struct dpu_dsc_cfg { DPU_HW_BLK_INFO; + unsigned long features; const struct dpu_dsc_sub_blks *sblk; }; @@ -573,7 +486,6 @@ struct dpu_dsc_cfg { * struct dpu_intf_cfg - information of timing engine blocks * @id enum identifying this block * @base register offset of this block - * @features bit mask identifying sub-blocks/features * @type: Interface type(DSI, DP, HDMI) * @controller_id: Controller Instance ID in case of multiple of intf type * @prog_fetch_lines_worst_case Worst case latency num lines needed to prefetch @@ -604,6 +516,7 @@ struct dpu_intf_cfg { */ struct dpu_wb_cfg { DPU_HW_BLK_INFO; + unsigned long features; u8 vbif_idx; u32 maxlinewidth; u32 xin_id; @@ -613,6 +526,16 @@ struct dpu_wb_cfg { enum dpu_clk_ctrl_type clk_ctrl; }; +/* + * struct dpu_cwb_cfg : MDP CWB mux instance info + * @id: enum identifying this block + * @base: register base offset to mdss + * @features bit mask identifying sub-blocks/features + */ +struct dpu_cwb_cfg { + DPU_HW_BLK_INFO; +}; + /** * struct dpu_vbif_dynamic_ot_cfg - dynamic OT setting * @pps pixel per seconds @@ -662,6 +585,7 @@ struct dpu_vbif_qos_tbl { */ struct dpu_vbif_cfg { DPU_HW_BLK_INFO; + unsigned long features; u32 default_ot_rd_limit; u32 default_ot_wr_limit; u32 xin_halt_timeout; @@ -679,7 +603,6 @@ struct dpu_vbif_cfg { * @name string name for debug purposes * @id enum identifying this block * @base register offset of this block - * @features bit mask identifying sub-blocks/features */ struct dpu_cdm_cfg { DPU_HW_BLK_INFO; @@ -815,6 +738,9 @@ struct dpu_mdss_cfg { u32 dspp_count; const struct dpu_dspp_cfg *dspp; + u32 cwb_count; + const struct dpu_cwb_cfg *cwb; + /* Add additional block data structures here */ const struct dpu_perf_cfg *perf; @@ -823,11 +749,13 @@ struct dpu_mdss_cfg { const struct dpu_format_extended *vig_formats; }; +extern const struct dpu_mdss_cfg dpu_glymur_cfg; extern const struct dpu_mdss_cfg dpu_msm8917_cfg; extern const struct dpu_mdss_cfg dpu_msm8937_cfg; extern const struct dpu_mdss_cfg dpu_msm8953_cfg; extern const struct dpu_mdss_cfg dpu_msm8996_cfg; extern const struct dpu_mdss_cfg dpu_msm8998_cfg; +extern const struct dpu_mdss_cfg dpu_sar2130p_cfg; extern const struct dpu_mdss_cfg dpu_sdm630_cfg; extern const struct dpu_mdss_cfg dpu_sdm660_cfg; extern const struct dpu_mdss_cfg dpu_sdm845_cfg; @@ -839,6 +767,7 @@ extern const struct dpu_mdss_cfg dpu_sm8250_cfg; extern const struct dpu_mdss_cfg dpu_sc7180_cfg; extern const struct dpu_mdss_cfg dpu_sm6115_cfg; extern const struct dpu_mdss_cfg dpu_sm6125_cfg; +extern const struct dpu_mdss_cfg dpu_sm6150_cfg; extern const struct dpu_mdss_cfg dpu_sm6350_cfg; extern const struct dpu_mdss_cfg dpu_qcm2290_cfg; extern const struct dpu_mdss_cfg dpu_sm6375_cfg; @@ -849,6 +778,7 @@ extern const struct dpu_mdss_cfg dpu_sm8450_cfg; extern const struct dpu_mdss_cfg dpu_sa8775p_cfg; extern const struct dpu_mdss_cfg dpu_sm8550_cfg; extern const struct dpu_mdss_cfg dpu_sm8650_cfg; +extern const struct dpu_mdss_cfg dpu_sm8750_cfg; extern const struct dpu_mdss_cfg dpu_x1e80100_cfg; #endif /* _DPU_HW_CATALOG_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c index ae1534c49ae0..3f88c3641d4a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c @@ -214,7 +214,9 @@ static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, const enum dpu_ mux_cfg = DPU_REG_READ(c, CDM_MUX); mux_cfg &= ~0xf; - if (pp) + if (pp >= PINGPONG_CWB_0) + mux_cfg |= 0xd; + else if (pp) mux_cfg |= (pp - PINGPONG_0) & 0x7; else mux_cfg |= 0xf; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index 4893f10d6a58..ac834db2e4c1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #include <linux/delay.h> @@ -31,15 +31,19 @@ #define CTL_MERGE_3D_ACTIVE 0x0E4 #define CTL_DSC_ACTIVE 0x0E8 #define CTL_WB_ACTIVE 0x0EC +#define CTL_CWB_ACTIVE 0x0F0 #define CTL_INTF_ACTIVE 0x0F4 #define CTL_CDM_ACTIVE 0x0F8 #define CTL_FETCH_PIPE_ACTIVE 0x0FC #define CTL_MERGE_3D_FLUSH 0x100 #define CTL_DSC_FLUSH 0x104 #define CTL_WB_FLUSH 0x108 +#define CTL_CWB_FLUSH 0x10C #define CTL_INTF_FLUSH 0x110 #define CTL_CDM_FLUSH 0x114 #define CTL_PERIPH_FLUSH 0x128 +#define CTL_PIPE_ACTIVE 0x12c +#define CTL_LAYER_ACTIVE 0x130 #define CTL_INTF_MASTER 0x134 #define CTL_DSPP_n_FLUSH(n) ((0x13C) + ((n) * 4)) @@ -53,6 +57,7 @@ #define PERIPH_IDX 30 #define INTF_IDX 31 #define WB_IDX 16 +#define CWB_IDX 28 #define DSPP_IDX 29 /* From DPU hw rev 7.x.x */ #define CTL_INVALID_BIT 0xffff #define CTL_DEFAULT_GROUP_ID 0xf @@ -61,6 +66,8 @@ static const u32 fetch_tbl[SSPP_MAX] = {CTL_INVALID_BIT, 16, 17, 18, 19, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0, 1, 2, 3, 4, 5}; +static const u32 lm_tbl[LM_MAX] = {CTL_INVALID_BIT, 0, 1, 2, 3, 4, 5, 6, 7}; + static int _mixer_stages(const struct dpu_lm_cfg *mixer, int count, enum dpu_lm lm) { @@ -110,6 +117,7 @@ static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx) ctx->pending_flush_mask = 0x0; ctx->pending_intf_flush_mask = 0; ctx->pending_wb_flush_mask = 0; + ctx->pending_cwb_flush_mask = 0; ctx->pending_merge_3d_flush_mask = 0; ctx->pending_dsc_flush_mask = 0; ctx->pending_cdm_flush_mask = 0; @@ -144,6 +152,9 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx) if (ctx->pending_flush_mask & BIT(WB_IDX)) DPU_REG_WRITE(&ctx->hw, CTL_WB_FLUSH, ctx->pending_wb_flush_mask); + if (ctx->pending_flush_mask & BIT(CWB_IDX)) + DPU_REG_WRITE(&ctx->hw, CTL_CWB_FLUSH, + ctx->pending_cwb_flush_mask); if (ctx->pending_flush_mask & BIT(DSPP_IDX)) for (dspp = DSPP_0; dspp < DSPP_MAX; dspp++) { @@ -254,6 +265,12 @@ static void dpu_hw_ctl_update_pending_flush_mixer(struct dpu_hw_ctl *ctx, case LM_5: ctx->pending_flush_mask |= BIT(20); break; + case LM_6: + ctx->pending_flush_mask |= BIT(21); + break; + case LM_7: + ctx->pending_flush_mask |= BIT(27); + break; default: break; } @@ -310,6 +327,13 @@ static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx, ctx->pending_flush_mask |= BIT(WB_IDX); } +static void dpu_hw_ctl_update_pending_flush_cwb_v1(struct dpu_hw_ctl *ctx, + enum dpu_cwb cwb) +{ + ctx->pending_cwb_flush_mask |= BIT(cwb - CWB_0); + ctx->pending_flush_mask |= BIT(CWB_IDX); +} + static void dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx, enum dpu_intf intf) { @@ -535,7 +559,7 @@ exit: DPU_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg[1]); DPU_REG_WRITE(c, CTL_LAYER_EXT2(lm), mixercfg[2]); DPU_REG_WRITE(c, CTL_LAYER_EXT3(lm), mixercfg[3]); - if ((test_bit(DPU_CTL_HAS_LAYER_EXT4, &ctx->caps->features))) + if (ctx->mdss_ver->core_major_ver >= 9) DPU_REG_WRITE(c, CTL_LAYER_EXT4(lm), mixercfg[4]); } @@ -547,13 +571,15 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, u32 intf_active = 0; u32 dsc_active = 0; u32 wb_active = 0; + u32 cwb_active = 0; u32 mode_sel = 0; + u32 merge_3d_active = 0; /* CTL_TOP[31:28] carries group_id to collate CTL paths * per VM. Explicitly disable it until VM support is * added in SW. Power on reset value is not disable. */ - if ((test_bit(DPU_CTL_VM_CFG, &ctx->caps->features))) + if (ctx->mdss_ver->core_major_ver >= 7) mode_sel = CTL_DEFAULT_GROUP_ID << 28; if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD) @@ -561,7 +587,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE); wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE); + cwb_active = DPU_REG_READ(c, CTL_CWB_ACTIVE); dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE); + merge_3d_active = DPU_REG_READ(c, CTL_MERGE_3D_ACTIVE); if (cfg->intf) intf_active |= BIT(cfg->intf - INTF_0); @@ -569,17 +597,24 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, if (cfg->wb) wb_active |= BIT(cfg->wb - WB_0); + if (cfg->cwb) + cwb_active |= cfg->cwb; + if (cfg->dsc) dsc_active |= cfg->dsc; + if (cfg->merge_3d) + merge_3d_active |= BIT(cfg->merge_3d - MERGE_3D_0); + DPU_REG_WRITE(c, CTL_TOP, mode_sel); DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active); DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active); + DPU_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active); DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active); + DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active); - if (cfg->merge_3d) - DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, - BIT(cfg->merge_3d - MERGE_3D_0)); + if (cfg->intf_master) + DPU_REG_WRITE(c, CTL_INTF_MASTER, BIT(cfg->intf_master - INTF_0)); if (cfg->cdm) DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm); @@ -623,7 +658,9 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx, { struct dpu_hw_blk_reg_map *c = &ctx->hw; u32 intf_active = 0; + u32 intf_master = 0; u32 wb_active = 0; + u32 cwb_active = 0; u32 merge3d_active = 0; u32 dsc_active; u32 cdm_active; @@ -643,12 +680,36 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx, merge3d_active); } - dpu_hw_ctl_clear_all_blendstages(ctx); + if (ctx->ops.clear_all_blendstages) + ctx->ops.clear_all_blendstages(ctx); + + if (ctx->ops.set_active_lms) + ctx->ops.set_active_lms(ctx, NULL); + + if (ctx->ops.set_active_fetch_pipes) + ctx->ops.set_active_fetch_pipes(ctx, NULL); + + if (ctx->ops.set_active_pipes) + ctx->ops.set_active_pipes(ctx, NULL); if (cfg->intf) { intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE); intf_active &= ~BIT(cfg->intf - INTF_0); DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active); + + intf_master = DPU_REG_READ(c, CTL_INTF_MASTER); + + /* Unset this intf as master, if it is the current master */ + if (intf_master == BIT(cfg->intf - INTF_0)) { + DPU_DEBUG_DRIVER("Unsetting INTF_%d master\n", cfg->intf - INTF_0); + DPU_REG_WRITE(c, CTL_INTF_MASTER, 0); + } + } + + if (cfg->cwb) { + cwb_active = DPU_REG_READ(c, CTL_CWB_ACTIVE); + cwb_active &= ~cfg->cwb; + DPU_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active); } if (cfg->wb) { @@ -670,8 +731,8 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx, } } -static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx, - unsigned long *fetch_active) +static void dpu_hw_ctl_set_active_fetch_pipes(struct dpu_hw_ctl *ctx, + unsigned long *fetch_active) { int i; u32 val = 0; @@ -687,54 +748,39 @@ static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx, DPU_REG_WRITE(&ctx->hw, CTL_FETCH_PIPE_ACTIVE, val); } -static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, - unsigned long cap) +static void dpu_hw_ctl_set_active_pipes(struct dpu_hw_ctl *ctx, + unsigned long *active_pipes) { - if (cap & BIT(DPU_CTL_ACTIVE_CFG)) { - ops->trigger_flush = dpu_hw_ctl_trigger_flush_v1; - ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg_v1; - ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1; - ops->update_pending_flush_intf = - dpu_hw_ctl_update_pending_flush_intf_v1; + int i; + u32 val = 0; - ops->update_pending_flush_periph = - dpu_hw_ctl_update_pending_flush_periph_v1; + if (active_pipes) { + for (i = 0; i < SSPP_MAX; i++) { + if (test_bit(i, active_pipes) && + fetch_tbl[i] != CTL_INVALID_BIT) + val |= BIT(fetch_tbl[i]); + } + } - ops->update_pending_flush_merge_3d = - dpu_hw_ctl_update_pending_flush_merge_3d_v1; - ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1; - ops->update_pending_flush_dsc = - dpu_hw_ctl_update_pending_flush_dsc_v1; - ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1; - } else { - ops->trigger_flush = dpu_hw_ctl_trigger_flush; - ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg; - ops->update_pending_flush_intf = - dpu_hw_ctl_update_pending_flush_intf; - ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb; - ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm; + DPU_REG_WRITE(&ctx->hw, CTL_PIPE_ACTIVE, val); +} + +static void dpu_hw_ctl_set_active_lms(struct dpu_hw_ctl *ctx, + unsigned long *active_lms) +{ + int i; + u32 val = 0; + + if (active_lms) { + for (i = LM_0; i < LM_MAX; i++) { + if (test_bit(i, active_lms) && + lm_tbl[i] != CTL_INVALID_BIT) + val |= BIT(lm_tbl[i]); + } } - ops->clear_pending_flush = dpu_hw_ctl_clear_pending_flush; - ops->update_pending_flush = dpu_hw_ctl_update_pending_flush; - ops->get_pending_flush = dpu_hw_ctl_get_pending_flush; - ops->get_flush_register = dpu_hw_ctl_get_flush_register; - ops->trigger_start = dpu_hw_ctl_trigger_start; - ops->is_started = dpu_hw_ctl_is_started; - ops->trigger_pending = dpu_hw_ctl_trigger_pending; - ops->reset = dpu_hw_ctl_reset_control; - ops->wait_reset_status = dpu_hw_ctl_wait_reset_status; - ops->clear_all_blendstages = dpu_hw_ctl_clear_all_blendstages; - ops->setup_blendstage = dpu_hw_ctl_setup_blendstage; - ops->update_pending_flush_sspp = dpu_hw_ctl_update_pending_flush_sspp; - ops->update_pending_flush_mixer = dpu_hw_ctl_update_pending_flush_mixer; - if (cap & BIT(DPU_CTL_DSPP_SUB_BLOCK_FLUSH)) - ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp_sub_blocks; - else - ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp; - if (cap & BIT(DPU_CTL_FETCH_ACTIVE)) - ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active; -}; + DPU_REG_WRITE(&ctx->hw, CTL_LAYER_ACTIVE, val); +} /** * dpu_hw_ctl_init() - Initializes the ctl_path hw driver object. @@ -742,12 +788,14 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, * @dev: Corresponding device for devres management * @cfg: ctl_path catalog entry for which driver object is required * @addr: mapped register io address of MDP + * @mdss_ver: dpu core's major and minor versions * @mixer_count: Number of mixers in @mixer * @mixer: Pointer to an array of Layer Mixers defined in the catalog */ struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev, const struct dpu_ctl_cfg *cfg, void __iomem *addr, + const struct dpu_mdss_version *mdss_ver, u32 mixer_count, const struct dpu_lm_cfg *mixer) { @@ -761,7 +809,59 @@ struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev, c->hw.log_mask = DPU_DBG_MASK_CTL; c->caps = cfg; - _setup_ctl_ops(&c->ops, c->caps->features); + c->mdss_ver = mdss_ver; + + if (mdss_ver->core_major_ver >= 5) { + c->ops.trigger_flush = dpu_hw_ctl_trigger_flush_v1; + c->ops.setup_intf_cfg = dpu_hw_ctl_intf_cfg_v1; + c->ops.reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1; + c->ops.update_pending_flush_intf = + dpu_hw_ctl_update_pending_flush_intf_v1; + + c->ops.update_pending_flush_periph = + dpu_hw_ctl_update_pending_flush_periph_v1; + + c->ops.update_pending_flush_merge_3d = + dpu_hw_ctl_update_pending_flush_merge_3d_v1; + c->ops.update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1; + c->ops.update_pending_flush_cwb = dpu_hw_ctl_update_pending_flush_cwb_v1; + c->ops.update_pending_flush_dsc = + dpu_hw_ctl_update_pending_flush_dsc_v1; + c->ops.update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1; + } else { + c->ops.trigger_flush = dpu_hw_ctl_trigger_flush; + c->ops.setup_intf_cfg = dpu_hw_ctl_intf_cfg; + c->ops.update_pending_flush_intf = + dpu_hw_ctl_update_pending_flush_intf; + c->ops.update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb; + c->ops.update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm; + } + c->ops.clear_pending_flush = dpu_hw_ctl_clear_pending_flush; + c->ops.update_pending_flush = dpu_hw_ctl_update_pending_flush; + c->ops.get_pending_flush = dpu_hw_ctl_get_pending_flush; + c->ops.get_flush_register = dpu_hw_ctl_get_flush_register; + c->ops.trigger_start = dpu_hw_ctl_trigger_start; + c->ops.is_started = dpu_hw_ctl_is_started; + c->ops.trigger_pending = dpu_hw_ctl_trigger_pending; + c->ops.reset = dpu_hw_ctl_reset_control; + c->ops.wait_reset_status = dpu_hw_ctl_wait_reset_status; + if (mdss_ver->core_major_ver < 12) { + c->ops.clear_all_blendstages = dpu_hw_ctl_clear_all_blendstages; + c->ops.setup_blendstage = dpu_hw_ctl_setup_blendstage; + } else { + c->ops.set_active_pipes = dpu_hw_ctl_set_active_pipes; + c->ops.set_active_lms = dpu_hw_ctl_set_active_lms; + } + c->ops.update_pending_flush_sspp = dpu_hw_ctl_update_pending_flush_sspp; + c->ops.update_pending_flush_mixer = dpu_hw_ctl_update_pending_flush_mixer; + if (mdss_ver->core_major_ver >= 7) + c->ops.update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp_sub_blocks; + else + c->ops.update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp; + + if (mdss_ver->core_major_ver >= 7) + c->ops.set_active_fetch_pipes = dpu_hw_ctl_set_active_fetch_pipes; + c->idx = cfg->id; c->mixer_count = mixer_count; c->mixer_hw_caps = mixer; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h index 85c6c835cc87..15931b22ec94 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _DPU_HW_CTL_H @@ -36,21 +36,25 @@ struct dpu_hw_stage_cfg { /** * struct dpu_hw_intf_cfg :Describes how the DPU writes data to output interface * @intf : Interface id + * @intf_master: Master interface id in the dual pipe topology * @mode_3d: 3d mux configuration * @merge_3d: 3d merge block used * @intf_mode_sel: Interface mode, cmd / vid * @cdm: CDM block used * @stream_sel: Stream selection for multi-stream interfaces * @dsc: DSC BIT masks used + * @cwb: CWB BIT masks used */ struct dpu_hw_intf_cfg { enum dpu_intf intf; + enum dpu_intf intf_master; enum dpu_wb wb; enum dpu_3d_blend_mode mode_3d; enum dpu_merge_3d merge_3d; enum dpu_ctl_mode_sel intf_mode_sel; enum dpu_cdm cdm; int stream_sel; + unsigned int cwb; unsigned int dsc; }; @@ -115,6 +119,15 @@ struct dpu_hw_ctl_ops { enum dpu_wb blk); /** + * OR in the given flushbits to the cached pending_(cwb_)flush_mask + * No effect on hardware + * @ctx : ctl path ctx pointer + * @blk : concurrent writeback block index + */ + void (*update_pending_flush_cwb)(struct dpu_hw_ctl *ctx, + enum dpu_cwb blk); + + /** * OR in the given flushbits to the cached pending_(intf_)flush_mask * No effect on hardware * @ctx : ctl path ctx pointer @@ -243,8 +256,25 @@ struct dpu_hw_ctl_ops { void (*setup_blendstage)(struct dpu_hw_ctl *ctx, enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg); - void (*set_active_pipes)(struct dpu_hw_ctl *ctx, + void (*set_active_fetch_pipes)(struct dpu_hw_ctl *ctx, unsigned long *fetch_active); + + /** + * Set active pipes attached to this CTL + * @ctx: ctl path ctx pointer + * @active_pipes: bitmap of enum dpu_sspp + */ + void (*set_active_pipes)(struct dpu_hw_ctl *ctx, + unsigned long *active_pipes); + + /** + * Set active layer mixers attached to this CTL + * @ctx: ctl path ctx pointer + * @active_lms: bitmap of enum dpu_lm + */ + void (*set_active_lms)(struct dpu_hw_ctl *ctx, + unsigned long *active_lms); + }; /** @@ -258,8 +288,10 @@ struct dpu_hw_ctl_ops { * @pending_flush_mask: storage for pending ctl_flush managed via ops * @pending_intf_flush_mask: pending INTF flush * @pending_wb_flush_mask: pending WB flush + * @pending_cwb_flush_mask: pending CWB flush * @pending_dsc_flush_mask: pending DSC flush * @pending_cdm_flush_mask: pending CDM flush + * @mdss_ver: MDSS revision information * @ops: operation list */ struct dpu_hw_ctl { @@ -274,12 +306,15 @@ struct dpu_hw_ctl { u32 pending_flush_mask; u32 pending_intf_flush_mask; u32 pending_wb_flush_mask; + u32 pending_cwb_flush_mask; u32 pending_periph_flush_mask; u32 pending_merge_3d_flush_mask; u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0]; u32 pending_dsc_flush_mask; u32 pending_cdm_flush_mask; + const struct dpu_mdss_version *mdss_ver; + /* ops */ struct dpu_hw_ctl_ops ops; }; @@ -297,6 +332,7 @@ static inline struct dpu_hw_ctl *to_dpu_hw_ctl(struct dpu_hw_blk *hw) struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev, const struct dpu_ctl_cfg *cfg, void __iomem *addr, + const struct dpu_mdss_version *mdss_ver, u32 mixer_count, const struct dpu_lm_cfg *mixer); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.c new file mode 100644 index 000000000000..ae785f4ff0d4 --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved + */ + +#include <drm/drm_managed.h> +#include "dpu_hw_cwb.h" + +#include <linux/bitfield.h> + +#define CWB_MUX 0x000 +#define CWB_MODE 0x004 + +/* CWB mux block bit definitions */ +#define CWB_MUX_MASK GENMASK(3, 0) +#define CWB_MODE_MASK GENMASK(2, 0) + +static void dpu_hw_cwb_config(struct dpu_hw_cwb *ctx, + struct dpu_hw_cwb_setup_cfg *cwb_cfg) +{ + struct dpu_hw_blk_reg_map *c = &ctx->hw; + int cwb_mux_cfg = 0xF; + enum dpu_pingpong pp; + enum cwb_mode_input input; + + if (!cwb_cfg) + return; + + input = cwb_cfg->input; + pp = cwb_cfg->pp_idx; + + if (input >= INPUT_MODE_MAX) + return; + + /* + * The CWB_MUX register takes the pingpong index for the real-time + * display + */ + if ((pp != PINGPONG_NONE) && (pp < PINGPONG_MAX)) + cwb_mux_cfg = FIELD_PREP(CWB_MUX_MASK, pp - PINGPONG_0); + + input = FIELD_PREP(CWB_MODE_MASK, input); + + DPU_REG_WRITE(c, CWB_MUX, cwb_mux_cfg); + DPU_REG_WRITE(c, CWB_MODE, input); +} + +/** + * dpu_hw_cwb_init() - Initializes the writeback hw driver object with cwb. + * @dev: Corresponding device for devres management + * @cfg: wb_path catalog entry for which driver object is required + * @addr: mapped register io address of MDP + * Return: Error code or allocated dpu_hw_wb context + */ +struct dpu_hw_cwb *dpu_hw_cwb_init(struct drm_device *dev, + const struct dpu_cwb_cfg *cfg, + void __iomem *addr) +{ + struct dpu_hw_cwb *c; + + if (!addr) + return ERR_PTR(-EINVAL); + + c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL); + if (!c) + return ERR_PTR(-ENOMEM); + + c->hw.blk_addr = addr + cfg->base; + c->hw.log_mask = DPU_DBG_MASK_CWB; + + c->idx = cfg->id; + c->ops.config_cwb = dpu_hw_cwb_config; + + return c; +} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h new file mode 100644 index 000000000000..96b6edf6b2bb --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved + */ + +#ifndef _DPU_HW_CWB_H +#define _DPU_HW_CWB_H + +#include "dpu_hw_util.h" + +struct dpu_hw_cwb; + +enum cwb_mode_input { + INPUT_MODE_LM_OUT, + INPUT_MODE_DSPP_OUT, + INPUT_MODE_MAX +}; + +/** + * struct dpu_hw_cwb_setup_cfg : Describes configuration for CWB mux + * @pp_idx: Index of the real-time pinpong that the CWB mux will + * feed the CWB mux + * @input: Input tap point + */ +struct dpu_hw_cwb_setup_cfg { + enum dpu_pingpong pp_idx; + enum cwb_mode_input input; +}; + +/** + * + * struct dpu_hw_cwb_ops : Interface to the cwb hw driver functions + * @config_cwb: configure CWB mux + */ +struct dpu_hw_cwb_ops { + void (*config_cwb)(struct dpu_hw_cwb *ctx, + struct dpu_hw_cwb_setup_cfg *cwb_cfg); +}; + +/** + * struct dpu_hw_cwb : CWB mux driver object + * @base: Hardware block base structure + * @hw: Block hardware details + * @idx: CWB index + * @ops: handle to operations possible for this CWB + */ +struct dpu_hw_cwb { + struct dpu_hw_blk base; + struct dpu_hw_blk_reg_map hw; + + enum dpu_cwb idx; + + struct dpu_hw_cwb_ops ops; +}; + +/** + * dpu_hw_cwb - convert base object dpu_hw_base to container + * @hw: Pointer to base hardware block + * return: Pointer to hardware block container + */ +static inline struct dpu_hw_cwb *to_dpu_hw_cwb(struct dpu_hw_blk *hw) +{ + return container_of(hw, struct dpu_hw_cwb, base); +} + +struct dpu_hw_cwb *dpu_hw_cwb_init(struct drm_device *dev, + const struct dpu_cwb_cfg *cfg, + void __iomem *addr); + +#endif /*_DPU_HW_CWB_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c index 657200401f57..3a149caa7ff4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c @@ -52,6 +52,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc, u32 slice_last_group_size; u32 det_thresh_flatness; bool is_cmd_mode = !(mode & DSC_MODE_VIDEO); + bool input_10_bits = dsc->bits_per_component == 10; DPU_REG_WRITE(c, DSC_COMMON_MODE, mode); @@ -68,7 +69,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc, data |= (dsc->line_buf_depth << 3); data |= (dsc->simple_422 << 2); data |= (dsc->convert_rgb << 1); - data |= dsc->bits_per_component; + data |= input_10_bits; DPU_REG_WRITE(c, DSC_ENC, data); @@ -180,26 +181,18 @@ static void dpu_hw_dsc_bind_pingpong_blk( DPU_REG_WRITE(c, dsc_ctl_offset, mux_cfg); } -static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops, - unsigned long cap) -{ - ops->dsc_disable = dpu_hw_dsc_disable; - ops->dsc_config = dpu_hw_dsc_config; - ops->dsc_config_thresh = dpu_hw_dsc_config_thresh; - if (cap & BIT(DPU_DSC_OUTPUT_CTRL)) - ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk; -}; - /** * dpu_hw_dsc_init() - Initializes the DSC hw driver object. * @dev: Corresponding device for devres management * @cfg: DSC catalog entry for which driver object is required * @addr: Mapped register io address of MDP + * @mdss_ver: dpu core's major and minor versions * Return: Error code or allocated dpu_hw_dsc context */ struct dpu_hw_dsc *dpu_hw_dsc_init(struct drm_device *dev, const struct dpu_dsc_cfg *cfg, - void __iomem *addr) + void __iomem *addr, + const struct dpu_mdss_version *mdss_ver) { struct dpu_hw_dsc *c; @@ -212,7 +205,12 @@ struct dpu_hw_dsc *dpu_hw_dsc_init(struct drm_device *dev, c->idx = cfg->id; c->caps = cfg; - _setup_dsc_ops(&c->ops, c->caps->features); + + c->ops.dsc_disable = dpu_hw_dsc_disable; + c->ops.dsc_config = dpu_hw_dsc_config; + c->ops.dsc_config_thresh = dpu_hw_dsc_config_thresh; + if (mdss_ver->core_major_ver >= 5) + c->ops.dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk; return c; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h index fc171bdeca48..cc7cc6f6f7cd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h @@ -64,18 +64,13 @@ struct dpu_hw_dsc { struct dpu_hw_dsc *dpu_hw_dsc_init(struct drm_device *dev, const struct dpu_dsc_cfg *cfg, - void __iomem *addr); + void __iomem *addr, + const struct dpu_mdss_version *mdss_ver); struct dpu_hw_dsc *dpu_hw_dsc_init_1_2(struct drm_device *dev, const struct dpu_dsc_cfg *cfg, void __iomem *addr); -/** - * dpu_hw_dsc_destroy - destroys dsc driver context - * @dsc: Pointer to dsc driver context returned by dpu_hw_dsc_init - */ -void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc); - static inline struct dpu_hw_dsc *to_dpu_hw_dsc(struct dpu_hw_blk *hw) { return container_of(hw, struct dpu_hw_dsc, base); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c index b9c433567262..b3395e9c34a1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c @@ -360,8 +360,7 @@ static void dpu_hw_dsc_bind_pingpong_blk_1_2(struct dpu_hw_dsc *hw_dsc, DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CTL, mux_cfg); } -static void _setup_dcs_ops_1_2(struct dpu_hw_dsc_ops *ops, - const unsigned long features) +static void _setup_dcs_ops_1_2(struct dpu_hw_dsc_ops *ops) { ops->dsc_disable = dpu_hw_dsc_disable_1_2; ops->dsc_config = dpu_hw_dsc_config_1_2; @@ -391,7 +390,7 @@ struct dpu_hw_dsc *dpu_hw_dsc_init_1_2(struct drm_device *dev, c->idx = cfg->id; c->caps = cfg; - _setup_dcs_ops_1_2(&c->ops, c->caps->features); + _setup_dcs_ops_1_2(&c->ops); return c; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c index 829ca272873e..54b20faa0b69 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c @@ -31,14 +31,14 @@ static void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx, u32 base; if (!ctx) { - DRM_ERROR("invalid ctx %pK\n", ctx); + DRM_ERROR("invalid ctx %p\n", ctx); return; } base = ctx->cap->sblk->pcc.base; if (!base) { - DRM_ERROR("invalid ctx %pK pcc base 0x%x\n", ctx, base); + DRM_ERROR("invalid ctx %p pcc base 0x%x\n", ctx, base); return; } @@ -63,13 +63,6 @@ static void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx, DPU_REG_WRITE(&ctx->hw, base, PCC_EN); } -static void _setup_dspp_ops(struct dpu_hw_dspp *c, - unsigned long features) -{ - if (test_bit(DPU_DSPP_PCC, &features)) - c->ops.setup_pcc = dpu_setup_dspp_pcc; -} - /** * dpu_hw_dspp_init() - Initializes the DSPP hw driver object. * should be called once before accessing every DSPP. @@ -97,7 +90,8 @@ struct dpu_hw_dspp *dpu_hw_dspp_init(struct drm_device *dev, /* Assign ops */ c->idx = cfg->id; c->cap = cfg; - _setup_dspp_ops(c, c->cap->features); + if (c->cap->sblk->pcc.base) + c->ops.setup_pcc = dpu_setup_dspp_pcc; return c; } 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 fb1d25baa518..a80ac82a9625 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -98,8 +98,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *intf, const struct dpu_hw_intf_timing_params *p, - const struct msm_format *fmt, - const struct dpu_mdss_version *mdss_ver) + const struct msm_format *fmt) { struct dpu_hw_blk_reg_map *c = &intf->hw; u32 hsync_period, vsync_period; @@ -180,7 +179,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *intf, /* TODO: handle DSC+DP case, we only handle DSC+DSI case so far */ if (p->compression_en && !dp_intf && - mdss_ver->core_major_ver >= 7) + intf->mdss_ver->core_major_ver >= 7) intf_cfg2 |= INTF_CFG2_DCE_DATA_COMPRESS; hsync_data_start_x = hsync_start_x; @@ -238,7 +237,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *intf, DPU_REG_WRITE(c, INTF_FRAME_LINE_COUNT_EN, 0x3); DPU_REG_WRITE(c, INTF_CONFIG, intf_cfg); DPU_REG_WRITE(c, INTF_PANEL_FORMAT, panel_format); - if (intf->cap->features & BIT(DPU_DATA_HCTL_EN)) { + if (intf->mdss_ver->core_major_ver >= 5) { /* * DATA_HCTL_EN controls data timing which can be different from * video timing. It is recommended to enable it for all cases, except @@ -309,9 +308,8 @@ static void dpu_hw_intf_get_status( struct dpu_hw_intf_status *s) { struct dpu_hw_blk_reg_map *c = &intf->hw; - unsigned long cap = intf->cap->features; - if (cap & BIT(DPU_INTF_STATUS_SUPPORTED)) + if (intf->mdss_ver->core_major_ver >= 5) s->is_en = DPU_REG_READ(c, INTF_STATUS) & BIT(0); else s->is_en = DPU_REG_READ(c, INTF_TIMING_ENGINE_EN); @@ -580,6 +578,8 @@ struct dpu_hw_intf *dpu_hw_intf_init(struct drm_device *dev, c->idx = cfg->id; c->cap = cfg; + c->mdss_ver = 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; @@ -588,7 +588,7 @@ struct dpu_hw_intf *dpu_hw_intf_init(struct drm_device *dev, 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)) + if (mdss_rev->core_major_ver >= 5) c->ops.bind_pingpong_blk = dpu_hw_intf_bind_pingpong_blk; /* INTF TE is only for DSI interfaces */ 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 114be272ac0a..f31067a9aaf1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h @@ -81,8 +81,7 @@ struct dpu_hw_intf_cmd_mode_cfg { struct dpu_hw_intf_ops { void (*setup_timing_gen)(struct dpu_hw_intf *intf, const struct dpu_hw_intf_timing_params *p, - const struct msm_format *fmt, - const struct dpu_mdss_version *mdss_ver); + const struct msm_format *fmt); void (*setup_prg_fetch)(struct dpu_hw_intf *intf, const struct dpu_hw_intf_prog_fetch *fetch); @@ -126,6 +125,8 @@ struct dpu_hw_intf { enum dpu_intf idx; const struct dpu_intf_cfg *cap; + const struct dpu_mdss_version *mdss_ver; + /* ops */ struct dpu_hw_intf_ops ops; }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c index 81b56f066519..e8a76d5192c2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c @@ -19,12 +19,28 @@ /* These register are offset to mixer base + stage base */ #define LM_BLEND0_OP 0x00 + +/* <v12 DPU with offset to mixer base + stage base */ #define LM_BLEND0_CONST_ALPHA 0x04 #define LM_FG_COLOR_FILL_COLOR_0 0x08 #define LM_FG_COLOR_FILL_COLOR_1 0x0C #define LM_FG_COLOR_FILL_SIZE 0x10 #define LM_FG_COLOR_FILL_XY 0x14 +/* >= v12 DPU */ +#define LM_BG_SRC_SEL_V12 0x14 +#define LM_BG_SRC_SEL_V12_RESET_VALUE 0x0000c0c0 +#define LM_BORDER_COLOR_0_V12 0x1c +#define LM_BORDER_COLOR_1_V12 0x20 + +/* >= v12 DPU with offset to mixer base + stage base */ +#define LM_BLEND0_FG_SRC_SEL_V12 0x04 +#define LM_BLEND0_CONST_ALPHA_V12 0x08 +#define LM_FG_COLOR_FILL_COLOR_0_V12 0x0c +#define LM_FG_COLOR_FILL_COLOR_1_V12 0x10 +#define LM_FG_COLOR_FILL_SIZE_V12 0x14 +#define LM_FG_COLOR_FILL_XY_V12 0x18 + #define LM_BLEND0_FG_ALPHA 0x04 #define LM_BLEND0_BG_ALPHA 0x08 @@ -83,6 +99,22 @@ static void dpu_hw_lm_setup_border_color(struct dpu_hw_mixer *ctx, } } +static void dpu_hw_lm_setup_border_color_v12(struct dpu_hw_mixer *ctx, + struct dpu_mdss_color *color, + u8 border_en) +{ + struct dpu_hw_blk_reg_map *c = &ctx->hw; + + if (border_en) { + DPU_REG_WRITE(c, LM_BORDER_COLOR_0_V12, + (color->color_0 & 0x3ff) | + ((color->color_1 & 0x3ff) << 16)); + DPU_REG_WRITE(c, LM_BORDER_COLOR_1_V12, + (color->color_2 & 0x3ff) | + ((color->color_3 & 0x3ff) << 16)); + } +} + static void dpu_hw_lm_setup_misr(struct dpu_hw_mixer *ctx) { dpu_hw_setup_misr(&ctx->hw, LM_MISR_CTRL, 0x0); @@ -112,6 +144,27 @@ static void dpu_hw_lm_setup_blend_config_combined_alpha(struct dpu_hw_mixer *ctx DPU_REG_WRITE(c, LM_BLEND0_OP + stage_off, blend_op); } +static void +dpu_hw_lm_setup_blend_config_combined_alpha_v12(struct dpu_hw_mixer *ctx, + u32 stage, u32 fg_alpha, + u32 bg_alpha, u32 blend_op) +{ + struct dpu_hw_blk_reg_map *c = &ctx->hw; + int stage_off; + u32 const_alpha; + + if (stage == DPU_STAGE_BASE) + return; + + stage_off = _stage_offset(ctx, stage); + if (WARN_ON(stage_off < 0)) + return; + + const_alpha = (bg_alpha & 0x3ff) | ((fg_alpha & 0x3ff) << 16); + DPU_REG_WRITE(c, LM_BLEND0_CONST_ALPHA_V12 + stage_off, const_alpha); + DPU_REG_WRITE(c, LM_BLEND0_OP + stage_off, blend_op); +} + static void dpu_hw_lm_setup_blend_config(struct dpu_hw_mixer *ctx, u32 stage, u32 fg_alpha, u32 bg_alpha, u32 blend_op) { @@ -144,18 +197,146 @@ static void dpu_hw_lm_setup_color3(struct dpu_hw_mixer *ctx, DPU_REG_WRITE(c, LM_OP_MODE, op_mode); } -static void _setup_mixer_ops(struct dpu_hw_lm_ops *ops, - unsigned long features) +static void dpu_hw_lm_setup_color3_v12(struct dpu_hw_mixer *ctx, + uint32_t mixer_op_mode) +{ + struct dpu_hw_blk_reg_map *c = &ctx->hw; + int op_mode, stages, stage_off, i; + + stages = ctx->cap->sblk->maxblendstages; + if (stages <= 0) + return; + + for (i = DPU_STAGE_0; i <= stages; i++) { + stage_off = _stage_offset(ctx, i); + if (WARN_ON(stage_off < 0)) + return; + + /* set color_out3 bit in blend0_op when enabled in mixer_op_mode */ + op_mode = DPU_REG_READ(c, LM_BLEND0_OP + stage_off); + if (mixer_op_mode & BIT(i)) + op_mode |= BIT(30); + else + op_mode &= ~BIT(30); + + DPU_REG_WRITE(c, LM_BLEND0_OP + stage_off, op_mode); + } +} + +static int _set_staged_sspp(u32 stage, struct dpu_hw_stage_cfg *stage_cfg, + int pipes_per_stage, u32 *value) { - ops->setup_mixer_out = dpu_hw_lm_setup_out; - if (test_bit(DPU_MIXER_COMBINED_ALPHA, &features)) - ops->setup_blend_config = dpu_hw_lm_setup_blend_config_combined_alpha; + int i; + u32 pipe_type = 0, pipe_id = 0, rec_id = 0; + u32 src_sel[PIPES_PER_STAGE]; + + *value = LM_BG_SRC_SEL_V12_RESET_VALUE; + if (!stage_cfg || !pipes_per_stage) + return 0; + + for (i = 0; i < pipes_per_stage; i++) { + enum dpu_sspp pipe = stage_cfg->stage[stage][i]; + enum dpu_sspp_multirect_index rect_index = stage_cfg->multirect_index[stage][i]; + + src_sel[i] = LM_BG_SRC_SEL_V12_RESET_VALUE; + + if (!pipe) + continue; + + /* translate pipe data to SWI pipe_type, pipe_id */ + if (pipe >= SSPP_DMA0 && pipe <= SSPP_DMA5) { + pipe_type = 0; + pipe_id = pipe - SSPP_DMA0; + } else if (pipe >= SSPP_VIG0 && pipe <= SSPP_VIG3) { + pipe_type = 1; + pipe_id = pipe - SSPP_VIG0; + } else { + DPU_ERROR("invalid rec-%d pipe:%d\n", i, pipe); + return -EINVAL; + } + + /* translate rec data to SWI rec_id */ + if (rect_index == DPU_SSPP_RECT_SOLO || rect_index == DPU_SSPP_RECT_0) { + rec_id = 0; + } else if (rect_index == DPU_SSPP_RECT_1) { + rec_id = 1; + } else { + DPU_ERROR("invalid rec-%d rect_index:%d\n", i, rect_index); + rec_id = 0; + } + + /* calculate SWI value for rec-0 and rec-1 and store it temporary buffer */ + src_sel[i] = (((pipe_type & 0x3) << 6) | ((rec_id & 0x3) << 4) | (pipe_id & 0xf)); + } + + /* calculate final SWI register value for rec-0 and rec-1 */ + *value = 0; + for (i = 0; i < pipes_per_stage; i++) + *value |= src_sel[i] << (i * 8); + + return 0; +} + +static int dpu_hw_lm_setup_blendstage(struct dpu_hw_mixer *ctx, enum dpu_lm lm, + struct dpu_hw_stage_cfg *stage_cfg) +{ + struct dpu_hw_blk_reg_map *c = &ctx->hw; + int i, ret, stages, stage_off, pipes_per_stage; + u32 value; + + stages = ctx->cap->sblk->maxblendstages; + if (stages <= 0) + return -EINVAL; + + if (test_bit(DPU_MIXER_SOURCESPLIT, &ctx->cap->features)) + pipes_per_stage = PIPES_PER_STAGE; else - ops->setup_blend_config = dpu_hw_lm_setup_blend_config; - ops->setup_alpha_out = dpu_hw_lm_setup_color3; - ops->setup_border_color = dpu_hw_lm_setup_border_color; - ops->setup_misr = dpu_hw_lm_setup_misr; - ops->collect_misr = dpu_hw_lm_collect_misr; + pipes_per_stage = 1; + + /* + * When stage configuration is empty, we can enable the + * border color by setting the corresponding LAYER_ACTIVE bit + * and un-staging all the pipes from the layer mixer. + */ + if (!stage_cfg) + DPU_REG_WRITE(c, LM_BG_SRC_SEL_V12, LM_BG_SRC_SEL_V12_RESET_VALUE); + + for (i = DPU_STAGE_0; i <= stages; i++) { + stage_off = _stage_offset(ctx, i); + if (stage_off < 0) + return stage_off; + + ret = _set_staged_sspp(i, stage_cfg, pipes_per_stage, &value); + if (ret) + return ret; + + DPU_REG_WRITE(c, LM_BLEND0_FG_SRC_SEL_V12 + stage_off, value); + } + + return 0; +} + +static int dpu_hw_lm_clear_all_blendstages(struct dpu_hw_mixer *ctx) +{ + struct dpu_hw_blk_reg_map *c = &ctx->hw; + int i, stages, stage_off; + + stages = ctx->cap->sblk->maxblendstages; + if (stages <= 0) + return -EINVAL; + + DPU_REG_WRITE(c, LM_BG_SRC_SEL_V12, LM_BG_SRC_SEL_V12_RESET_VALUE); + + for (i = DPU_STAGE_0; i <= stages; i++) { + stage_off = _stage_offset(ctx, i); + if (stage_off < 0) + return stage_off; + + DPU_REG_WRITE(c, LM_BLEND0_FG_SRC_SEL_V12 + stage_off, + LM_BG_SRC_SEL_V12_RESET_VALUE); + } + + return 0; } /** @@ -164,10 +345,12 @@ static void _setup_mixer_ops(struct dpu_hw_lm_ops *ops, * @dev: Corresponding device for devres management * @cfg: mixer catalog entry for which driver object is required * @addr: mapped register io address of MDP + * @mdss_ver: DPU core's major and minor versions */ struct dpu_hw_mixer *dpu_hw_lm_init(struct drm_device *dev, const struct dpu_lm_cfg *cfg, - void __iomem *addr) + void __iomem *addr, + const struct dpu_mdss_version *mdss_ver) { struct dpu_hw_mixer *c; @@ -186,7 +369,24 @@ struct dpu_hw_mixer *dpu_hw_lm_init(struct drm_device *dev, /* Assign ops */ c->idx = cfg->id; c->cap = cfg; - _setup_mixer_ops(&c->ops, c->cap->features); + c->ops.setup_mixer_out = dpu_hw_lm_setup_out; + if (mdss_ver->core_major_ver >= 12) + c->ops.setup_blend_config = dpu_hw_lm_setup_blend_config_combined_alpha_v12; + else if (mdss_ver->core_major_ver >= 4) + c->ops.setup_blend_config = dpu_hw_lm_setup_blend_config_combined_alpha; + else + c->ops.setup_blend_config = dpu_hw_lm_setup_blend_config; + if (mdss_ver->core_major_ver < 12) { + c->ops.setup_alpha_out = dpu_hw_lm_setup_color3; + c->ops.setup_border_color = dpu_hw_lm_setup_border_color; + } else { + c->ops.setup_alpha_out = dpu_hw_lm_setup_color3_v12; + c->ops.setup_blendstage = dpu_hw_lm_setup_blendstage; + c->ops.clear_all_blendstages = dpu_hw_lm_clear_all_blendstages; + c->ops.setup_border_color = dpu_hw_lm_setup_border_color_v12; + } + c->ops.setup_misr = dpu_hw_lm_setup_misr; + c->ops.collect_misr = dpu_hw_lm_collect_misr; return c; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h index 6f60fa9b3cd7..1b9ecd082d7f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h @@ -11,6 +11,7 @@ #include "dpu_hw_util.h" struct dpu_hw_mixer; +struct dpu_hw_stage_cfg; struct dpu_hw_mixer_cfg { u32 out_width; @@ -49,6 +50,23 @@ struct dpu_hw_lm_ops { void (*setup_alpha_out)(struct dpu_hw_mixer *ctx, uint32_t mixer_op); /** + * Clear layer mixer to pipe configuration + * @ctx : mixer ctx pointer + * Returns: 0 on success or -error + */ + int (*clear_all_blendstages)(struct dpu_hw_mixer *ctx); + + /** + * Configure layer mixer to pipe configuration + * @ctx : mixer ctx pointer + * @lm : layer mixer enumeration + * @stage_cfg : blend stage configuration + * Returns: 0 on success or -error + */ + int (*setup_blendstage)(struct dpu_hw_mixer *ctx, enum dpu_lm lm, + struct dpu_hw_stage_cfg *stage_cfg); + + /** * setup_border_color : enable/disable border color */ void (*setup_border_color)(struct dpu_hw_mixer *ctx, @@ -95,6 +113,7 @@ static inline struct dpu_hw_mixer *to_dpu_hw_mixer(struct dpu_hw_blk *hw) struct dpu_hw_mixer *dpu_hw_lm_init(struct drm_device *dev, const struct dpu_lm_cfg *cfg, - void __iomem *addr); + void __iomem *addr, + const struct dpu_mdss_version *mdss_ver); #endif /*_DPU_HW_LM_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h index f8806a4d317b..31451241f083 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */ #ifndef _DPU_HW_MDSS_H @@ -32,7 +34,9 @@ #define DPU_MAX_PLANES 4 #endif +#define STAGES_PER_PLANE 2 #define PIPES_PER_STAGE 2 +#define PIPES_PER_PLANE (PIPES_PER_STAGE * STAGES_PER_PLANE) #ifndef DPU_MAX_DE_CURVES #define DPU_MAX_DE_CURVES 3 #endif @@ -75,12 +79,14 @@ enum dpu_hw_blk_type { DPU_HW_BLK_LM, DPU_HW_BLK_CTL, DPU_HW_BLK_PINGPONG, + DPU_HW_BLK_DCWB_PINGPONG, DPU_HW_BLK_INTF, DPU_HW_BLK_WB, DPU_HW_BLK_DSPP, DPU_HW_BLK_MERGE_3D, DPU_HW_BLK_DSC, DPU_HW_BLK_CDM, + DPU_HW_BLK_CWB, DPU_HW_BLK_MAX, }; @@ -121,6 +127,7 @@ enum dpu_lm { LM_4, LM_5, LM_6, + LM_7, LM_MAX }; @@ -144,6 +151,10 @@ enum dpu_dspp { DSPP_1, DSPP_2, DSPP_3, + DSPP_4, + DSPP_5, + DSPP_6, + DSPP_7, DSPP_MAX }; @@ -154,6 +165,8 @@ enum dpu_ctl { CTL_3, CTL_4, CTL_5, + CTL_6, + CTL_7, CTL_MAX }; @@ -165,6 +178,8 @@ enum dpu_dsc { DSC_3, DSC_4, DSC_5, + DSC_6, + DSC_7, DSC_MAX }; @@ -183,8 +198,10 @@ enum dpu_pingpong { PINGPONG_5, PINGPONG_6, PINGPONG_7, - PINGPONG_8, - PINGPONG_9, + PINGPONG_CWB_0, + PINGPONG_CWB_1, + PINGPONG_CWB_2, + PINGPONG_CWB_3, PINGPONG_S0, PINGPONG_MAX }; @@ -195,6 +212,7 @@ enum dpu_merge_3d { MERGE_3D_2, MERGE_3D_3, MERGE_3D_4, + MERGE_3D_5, MERGE_3D_MAX }; @@ -350,6 +368,7 @@ struct dpu_mdss_color { #define DPU_DBG_MASK_DSPP (1 << 10) #define DPU_DBG_MASK_DSC (1 << 11) #define DPU_DBG_MASK_CDM (1 << 12) +#define DPU_DBG_MASK_CWB (1 << 13) /** * struct dpu_hw_tear_check - Struct contains parameters to configure diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c index 0b3325f9c870..83b1dbecddd2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c @@ -33,8 +33,7 @@ static void dpu_hw_merge_3d_setup_3d_mode(struct dpu_hw_merge_3d *merge_3d, } } -static void _setup_merge_3d_ops(struct dpu_hw_merge_3d *c, - unsigned long features) +static void _setup_merge_3d_ops(struct dpu_hw_merge_3d *c) { c->ops.setup_3d_mode = dpu_hw_merge_3d_setup_3d_mode; }; @@ -62,7 +61,7 @@ struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(struct drm_device *dev, c->idx = cfg->id; c->caps = cfg; - _setup_merge_3d_ops(c, c->caps->features); + _setup_merge_3d_ops(c); return c; } 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 36c0ec775b92..138071be5649 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c @@ -319,13 +319,13 @@ struct dpu_hw_pingpong *dpu_hw_pingpong_init(struct drm_device *dev, c->ops.disable_autorefresh = dpu_hw_pp_disable_autorefresh; } - if (test_bit(DPU_PINGPONG_DSC, &cfg->features)) { + if (mdss_rev->core_major_ver < 7) { 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, &cfg->features)) + if (mdss_rev->core_major_ver >= 3) c->ops.setup_dither = dpu_hw_pp_setup_dither; return c; 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 32c7c8084553..6f1fc790ad6d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -10,11 +10,11 @@ #include "dpu_hw_sspp.h" #include "dpu_kms.h" -#include "msm_mdss.h" - #include <drm/drm_file.h> #include <drm/drm_managed.h> +#include <linux/soc/qcom/ubwc.h> + #define DPU_FETCH_CONFIG_RESET_VALUE 0x00000087 /* SSPP registers */ @@ -543,7 +543,7 @@ static void dpu_hw_sspp_setup_qos_lut(struct dpu_hw_sspp *ctx, return; _dpu_hw_setup_qos_lut(&ctx->hw, SSPP_DANGER_LUT, - test_bit(DPU_SSPP_QOS_8LVL, &ctx->cap->features), + ctx->mdss_ver->core_major_ver >= 4, cfg); } @@ -684,7 +684,7 @@ int _dpu_hw_sspp_init_debugfs(struct dpu_hw_sspp *hw_pipe, struct dpu_kms *kms, struct dpu_hw_sspp *dpu_hw_sspp_init(struct drm_device *dev, const struct dpu_sspp_cfg *cfg, void __iomem *addr, - const struct msm_mdss_data *mdss_data, + const struct qcom_ubwc_cfg_data *mdss_data, const struct dpu_mdss_version *mdss_rev) { struct dpu_hw_sspp *hw_pipe; @@ -703,6 +703,9 @@ struct dpu_hw_sspp *dpu_hw_sspp_init(struct drm_device *dev, hw_pipe->ubwc = mdss_data; hw_pipe->idx = cfg->id; hw_pipe->cap = cfg; + + hw_pipe->mdss_ver = mdss_rev; + _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 56a0edf2a57c..bdac5c04bf79 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h @@ -308,12 +308,14 @@ struct dpu_hw_sspp_ops { struct dpu_hw_sspp { struct dpu_hw_blk base; struct dpu_hw_blk_reg_map hw; - const struct msm_mdss_data *ubwc; + const struct qcom_ubwc_cfg_data *ubwc; /* Pipe */ enum dpu_sspp idx; const struct dpu_sspp_cfg *cap; + const struct dpu_mdss_version *mdss_ver; + /* Ops */ struct dpu_hw_sspp_ops ops; }; @@ -323,7 +325,7 @@ struct dpu_kms; struct dpu_hw_sspp *dpu_hw_sspp_init(struct drm_device *dev, const struct dpu_sspp_cfg *cfg, void __iomem *addr, - const struct msm_mdss_data *mdss_data, + const struct qcom_ubwc_cfg_data *mdss_data, const struct dpu_mdss_version *mdss_rev); int _dpu_hw_sspp_init_debugfs(struct dpu_hw_sspp *hw_pipe, struct dpu_kms *kms, 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 ad19330de61a..96dc10589bee 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c @@ -264,15 +264,15 @@ static void dpu_hw_dp_phy_intf_sel(struct dpu_hw_mdp *mdp, } static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops, - unsigned long cap, const struct dpu_mdss_version *mdss_rev) + const struct dpu_mdss_version *mdss_rev) { ops->setup_split_pipe = dpu_hw_setup_split_pipe; ops->setup_clk_force_ctrl = dpu_hw_setup_clk_force_ctrl; ops->get_danger_status = dpu_hw_get_danger_status; - if (cap & BIT(DPU_MDP_VSYNC_SEL)) + if (mdss_rev->core_major_ver < 5) ops->setup_vsync_source = dpu_hw_setup_vsync_sel; - else + else if (mdss_rev->core_major_ver < 8) ops->setup_vsync_source = dpu_hw_setup_wd_timer; ops->get_safe_status = dpu_hw_get_safe_status; @@ -280,7 +280,8 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops, if (mdss_rev->core_major_ver >= 5) ops->dp_phy_intf_sel = dpu_hw_dp_phy_intf_sel; - if (cap & BIT(DPU_MDP_AUDIO_SELECT)) + if (mdss_rev->core_major_ver == 4 || + mdss_rev->core_major_ver == 5) ops->intf_audio_select = dpu_hw_intf_audio_select; } @@ -312,7 +313,7 @@ struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev, * Assign ops */ mdp->caps = cfg; - _setup_mdp_ops(&mdp->ops, mdp->caps->features, mdss_rev); + _setup_mdp_ops(&mdp->ops, mdss_rev); return mdp; } 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 fb9f90957762..478a091aeccf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c @@ -173,7 +173,9 @@ static void dpu_hw_wb_bind_pingpong_blk( mux_cfg = DPU_REG_READ(c, WB_MUX); mux_cfg &= ~0xf; - if (pp) + if (pp >= PINGPONG_CWB_0) + mux_cfg |= (pp < PINGPONG_CWB_2) ? 0xd : 0xb; + else if (pp) mux_cfg |= (pp - PINGPONG_0) & 0x7; else mux_cfg |= 0xf; @@ -206,7 +208,7 @@ static void _setup_wb_ops(struct dpu_hw_wb_ops *ops, if (test_bit(DPU_WB_CDP, &features)) ops->setup_cdp = dpu_hw_wb_setup_cdp; - if (test_bit(DPU_WB_INPUT_CTRL, &features)) + if (mdss_rev->core_major_ver >= 5) ops->bind_pingpong_blk = dpu_hw_wb_bind_pingpong_blk; if (mdss_rev->core_major_ver >= 9) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ca4847b2b738..f4c9767c418d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -2,7 +2,7 @@ /* * Copyright (C) 2013 Red Hat * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. * * Author: Rob Clark <robdclark@gmail.com> */ @@ -20,9 +20,10 @@ #include <drm/drm_vblank.h> #include <drm/drm_writeback.h> +#include <linux/soc/qcom/ubwc.h> + #include "msm_drv.h" #include "msm_mmu.h" -#include "msm_mdss.h" #include "msm_gem.h" #include "disp/msm_disp_snapshot.h" @@ -51,6 +52,9 @@ #define DPU_DEBUGFS_DIR "msm_dpu" #define DPU_DEBUGFS_HWMASKNAME "hw_log_mask" +bool dpu_use_virtual_planes; +module_param(dpu_use_virtual_planes, bool, 0); + static int dpu_kms_hw_init(struct msm_kms *kms); static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms); @@ -443,6 +447,19 @@ static void dpu_kms_disable_commit(struct msm_kms *kms) pm_runtime_put_sync(&dpu_kms->pdev->dev); } +static int dpu_kms_check_mode_changed(struct msm_kms *kms, struct drm_atomic_state *state) +{ + struct drm_crtc_state *new_crtc_state; + struct drm_crtc_state *old_crtc_state; + struct drm_crtc *crtc; + int i; + + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) + dpu_crtc_check_mode_changed(old_crtc_state, new_crtc_state); + + return 0; +} + static void dpu_kms_flush_commit(struct msm_kms *kms, unsigned crtc_mask) { struct dpu_kms *dpu_kms = to_dpu_kms(kms); @@ -566,7 +583,7 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev, struct msm_display_info info; int i, rc = 0; - if (!(priv->dsi[0] || priv->dsi[1])) + if (!(priv->kms->dsi[0] || priv->kms->dsi[1])) return rc; /* @@ -577,26 +594,26 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev, * * TODO: Support swapping DSI0 and DSI1 in the bonded setup. */ - for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) { + for (i = 0; i < ARRAY_SIZE(priv->kms->dsi); i++) { int other = (i + 1) % 2; - if (!priv->dsi[i]) + if (!priv->kms->dsi[i]) continue; - if (msm_dsi_is_bonded_dsi(priv->dsi[i]) && - !msm_dsi_is_master_dsi(priv->dsi[i])) + if (msm_dsi_is_bonded_dsi(priv->kms->dsi[i]) && + !msm_dsi_is_master_dsi(priv->kms->dsi[i])) continue; memset(&info, 0, sizeof(info)); info.intf_type = INTF_DSI; info.h_tile_instance[info.num_of_h_tiles++] = i; - if (msm_dsi_is_bonded_dsi(priv->dsi[i])) + if (msm_dsi_is_bonded_dsi(priv->kms->dsi[i])) info.h_tile_instance[info.num_of_h_tiles++] = other; - info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->dsi[i]); + info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->kms->dsi[i]); - rc = dpu_kms_dsi_set_te_source(&info, priv->dsi[i]); + rc = dpu_kms_dsi_set_te_source(&info, priv->kms->dsi[i]); if (rc) { DPU_ERROR("failed to identify TE source for dsi display\n"); return rc; @@ -608,15 +625,15 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev, return PTR_ERR(encoder); } - rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder); + rc = msm_dsi_modeset_init(priv->kms->dsi[i], dev, encoder); if (rc) { DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n", i, rc); break; } - if (msm_dsi_is_bonded_dsi(priv->dsi[i]) && priv->dsi[other]) { - rc = msm_dsi_modeset_init(priv->dsi[other], dev, encoder); + if (msm_dsi_is_bonded_dsi(priv->kms->dsi[i]) && priv->kms->dsi[other]) { + rc = msm_dsi_modeset_init(priv->kms->dsi[other], dev, encoder); if (rc) { DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n", other, rc); @@ -638,8 +655,8 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, int rc; int i; - for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { - if (!priv->dp[i]) + for (i = 0; i < ARRAY_SIZE(priv->kms->dp); i++) { + if (!priv->kms->dp[i]) continue; memset(&info, 0, sizeof(info)); @@ -654,7 +671,7 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, } yuv_supported = !!dpu_kms->catalog->cdm; - rc = msm_dp_modeset_init(priv->dp[i], dev, encoder, yuv_supported); + rc = msm_dp_modeset_init(priv->kms->dp[i], dev, encoder, yuv_supported); if (rc) { DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); return rc; @@ -672,7 +689,7 @@ static int _dpu_kms_initialize_hdmi(struct drm_device *dev, struct msm_display_info info; int rc; - if (!priv->hdmi) + if (!priv->kms->hdmi) return 0; memset(&info, 0, sizeof(info)); @@ -686,7 +703,7 @@ static int _dpu_kms_initialize_hdmi(struct drm_device *dev, return PTR_ERR(encoder); } - rc = msm_hdmi_modeset_init(priv->hdmi, dev, encoder); + rc = msm_hdmi_modeset_init(priv->kms->hdmi, dev, encoder); if (rc) { DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); return rc; @@ -808,8 +825,11 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms) return ret; num_encoders = 0; - drm_for_each_encoder(encoder, dev) + drm_for_each_encoder(encoder, dev) { num_encoders++; + if (catalog->cwb_count > 0) + encoder->possible_clones = dpu_encoder_get_clones(encoder); + } max_crtc_count = min(catalog->mixer_count, num_encoders); @@ -829,8 +849,11 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms) type, catalog->sspp[i].features, catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR)); - plane = dpu_plane_init(dev, catalog->sspp[i].id, type, - (1UL << max_crtc_count) - 1); + if (dpu_use_virtual_planes) + plane = dpu_plane_init_virtual(dev, type, (1UL << max_crtc_count) - 1); + else + plane = dpu_plane_init(dev, catalog->sspp[i].id, type, + (1UL << max_crtc_count) - 1); if (IS_ERR(plane)) { DPU_ERROR("dpu_plane_init failed\n"); ret = PTR_ERR(plane); @@ -852,12 +875,11 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms) ret = PTR_ERR(crtc); return ret; } - priv->num_crtcs++; } /* All CRTCs are compatible with all encoders */ drm_for_each_encoder(encoder, dev) - encoder->possible_crtcs = (1 << priv->num_crtcs) - 1; + encoder->possible_crtcs = (1 << dev->mode_config.num_crtc) - 1; return 0; } @@ -932,12 +954,14 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k /* dump CTL sub-blocks HW regs info */ for (i = 0; i < cat->ctl_count; i++) msm_disp_snapshot_add_block(disp_state, cat->ctl[i].len, - dpu_kms->mmio + cat->ctl[i].base, cat->ctl[i].name); + dpu_kms->mmio + cat->ctl[i].base, "%s", + cat->ctl[i].name); /* dump DSPP sub-blocks HW regs info */ for (i = 0; i < cat->dspp_count; i++) { base = dpu_kms->mmio + cat->dspp[i].base; - msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, base, cat->dspp[i].name); + msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, base, + "%s", cat->dspp[i].name); if (cat->dspp[i].sblk && cat->dspp[i].sblk->pcc.len > 0) msm_disp_snapshot_add_block(disp_state, cat->dspp[i].sblk->pcc.len, @@ -949,13 +973,14 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k /* dump INTF sub-blocks HW regs info */ for (i = 0; i < cat->intf_count; i++) msm_disp_snapshot_add_block(disp_state, cat->intf[i].len, - dpu_kms->mmio + cat->intf[i].base, cat->intf[i].name); + dpu_kms->mmio + cat->intf[i].base, "%s", + cat->intf[i].name); /* dump PP sub-blocks HW regs info */ for (i = 0; i < cat->pingpong_count; i++) { base = dpu_kms->mmio + cat->pingpong[i].base; msm_disp_snapshot_add_block(disp_state, cat->pingpong[i].len, base, - cat->pingpong[i].name); + "%s", cat->pingpong[i].name); /* TE2 sub-block has length of 0, so will not print it */ @@ -969,7 +994,8 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k /* dump SSPP sub-blocks HW regs info */ for (i = 0; i < cat->sspp_count; i++) { base = dpu_kms->mmio + cat->sspp[i].base; - msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, base, cat->sspp[i].name); + msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, base, + "%s", cat->sspp[i].name); if (cat->sspp[i].sblk && cat->sspp[i].sblk->scaler_blk.len > 0) msm_disp_snapshot_add_block(disp_state, cat->sspp[i].sblk->scaler_blk.len, @@ -987,14 +1013,16 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k /* dump LM sub-blocks HW regs info */ for (i = 0; i < cat->mixer_count; i++) msm_disp_snapshot_add_block(disp_state, cat->mixer[i].len, - dpu_kms->mmio + cat->mixer[i].base, cat->mixer[i].name); + dpu_kms->mmio + cat->mixer[i].base, + "%s", cat->mixer[i].name); /* dump WB sub-blocks HW regs info */ for (i = 0; i < cat->wb_count; i++) msm_disp_snapshot_add_block(disp_state, cat->wb[i].len, - dpu_kms->mmio + cat->wb[i].base, cat->wb[i].name); + dpu_kms->mmio + cat->wb[i].base, "%s", + cat->wb[i].name); - if (cat->mdp[0].features & BIT(DPU_MDP_PERIPH_0_REMOVED)) { + if (dpu_kms->catalog->mdss_ver->core_major_ver >= 8) { msm_disp_snapshot_add_block(disp_state, MDP_PERIPH_TOP0, dpu_kms->mmio + cat->mdp[0].base, "top"); msm_disp_snapshot_add_block(disp_state, cat->mdp[0].len - MDP_PERIPH_TOP0_END, @@ -1004,12 +1032,18 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k dpu_kms->mmio + cat->mdp[0].base, "top"); } + /* dump CWB sub-blocks HW regs info */ + for (i = 0; i < cat->cwb_count; i++) + msm_disp_snapshot_add_block(disp_state, cat->cwb[i].len, + dpu_kms->mmio + cat->cwb[i].base, cat->cwb[i].name); + /* dump DSC sub-blocks HW regs info */ for (i = 0; i < cat->dsc_count; i++) { base = dpu_kms->mmio + cat->dsc[i].base; - msm_disp_snapshot_add_block(disp_state, cat->dsc[i].len, base, cat->dsc[i].name); + msm_disp_snapshot_add_block(disp_state, cat->dsc[i].len, base, + "%s", cat->dsc[i].name); - if (cat->dsc[i].features & BIT(DPU_DSC_HW_REV_1_2)) { + if (cat->mdss_ver->core_major_ver >= 7) { struct dpu_dsc_blk enc = cat->dsc[i].sblk->enc; struct dpu_dsc_blk ctl = cat->dsc[i].sblk->ctl; @@ -1022,7 +1056,16 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k if (cat->cdm) msm_disp_snapshot_add_block(disp_state, cat->cdm->len, - dpu_kms->mmio + cat->cdm->base, cat->cdm->name); + dpu_kms->mmio + cat->cdm->base, + "%s", cat->cdm->name); + + for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { + const struct dpu_vbif_cfg *vbif = &dpu_kms->catalog->vbif[i]; + + msm_disp_snapshot_add_block(disp_state, vbif->len, + dpu_kms->vbif[vbif->id] + vbif->base, + "%s", vbif->name); + } pm_runtime_put_sync(&dpu_kms->pdev->dev); } @@ -1035,6 +1078,7 @@ static const struct msm_kms_funcs kms_funcs = { .irq = dpu_core_irq, .enable_commit = dpu_kms_enable_commit, .disable_commit = dpu_kms_disable_commit, + .check_mode_changed = dpu_kms_check_mode_changed, .flush_commit = dpu_kms_flush_commit, .wait_flush = dpu_kms_wait_flush, .complete_commit = dpu_kms_complete_commit, @@ -1051,26 +1095,26 @@ static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms) { struct msm_mmu *mmu; - if (!dpu_kms->base.aspace) + if (!dpu_kms->base.vm) return; - mmu = dpu_kms->base.aspace->mmu; + mmu = to_msm_vm(dpu_kms->base.vm)->mmu; mmu->funcs->detach(mmu); - msm_gem_address_space_put(dpu_kms->base.aspace); + drm_gpuvm_put(dpu_kms->base.vm); - dpu_kms->base.aspace = NULL; + dpu_kms->base.vm = NULL; } static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms) { - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; - aspace = msm_kms_init_aspace(dpu_kms->dev); - if (IS_ERR(aspace)) - return PTR_ERR(aspace); + vm = msm_kms_init_vm(dpu_kms->dev, dpu_kms->dev->dev->parent); + if (IS_ERR(vm)) + return PTR_ERR(vm); - dpu_kms->base.aspace = aspace; + dpu_kms->base.vm = vm; return 0; } @@ -1145,10 +1189,10 @@ static int dpu_kms_hw_init(struct msm_kms *kms) goto err_pm_put; } - dpu_kms->mdss = msm_mdss_get_mdss_data(dpu_kms->pdev->dev.parent); + dpu_kms->mdss = qcom_ubwc_config_get_data(); if (IS_ERR(dpu_kms->mdss)) { rc = PTR_ERR(dpu_kms->mdss); - DPU_ERROR("failed to get MDSS data: %d\n", rc); + DPU_ERROR("failed to get UBWC config data: %d\n", rc); goto err_pm_put; } @@ -1301,7 +1345,7 @@ static int dpu_kms_mmap_mdp5(struct dpu_kms *dpu_kms) dpu_kms->mmio = NULL; return ret; } - DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio); + DRM_DEBUG("mapped dpu address space @%p\n", dpu_kms->mmio); dpu_kms->vbif[VBIF_RT] = msm_ioremap_mdss(mdss_dev, dpu_kms->pdev, @@ -1336,7 +1380,7 @@ static int dpu_kms_mmap_dpu(struct dpu_kms *dpu_kms) dpu_kms->mmio = NULL; return ret; } - DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio); + DRM_DEBUG("mapped dpu address space @%p\n", dpu_kms->mmio); dpu_kms->vbif[VBIF_RT] = msm_ioremap(pdev, "vbif"); if (IS_ERR(dpu_kms->vbif[VBIF_RT])) { @@ -1461,6 +1505,7 @@ static const struct dev_pm_ops dpu_pm_ops = { }; static const struct of_device_id dpu_dt_match[] = { + { .compatible = "qcom,glymur-dpu", .data = &dpu_glymur_cfg, }, { .compatible = "qcom,msm8917-mdp5", .data = &dpu_msm8917_cfg, }, { .compatible = "qcom,msm8937-mdp5", .data = &dpu_msm8937_cfg, }, { .compatible = "qcom,msm8953-mdp5", .data = &dpu_msm8953_cfg, }, @@ -1468,6 +1513,7 @@ static const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,msm8998-dpu", .data = &dpu_msm8998_cfg, }, { .compatible = "qcom,qcm2290-dpu", .data = &dpu_qcm2290_cfg, }, { .compatible = "qcom,sa8775p-dpu", .data = &dpu_sa8775p_cfg, }, + { .compatible = "qcom,sar2130p-dpu", .data = &dpu_sar2130p_cfg, }, { .compatible = "qcom,sdm630-mdp5", .data = &dpu_sdm630_cfg, }, { .compatible = "qcom,sdm660-mdp5", .data = &dpu_sdm660_cfg, }, { .compatible = "qcom,sdm670-dpu", .data = &dpu_sdm670_cfg, }, @@ -1478,6 +1524,7 @@ static const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,sc8280xp-dpu", .data = &dpu_sc8280xp_cfg, }, { .compatible = "qcom,sm6115-dpu", .data = &dpu_sm6115_cfg, }, { .compatible = "qcom,sm6125-dpu", .data = &dpu_sm6125_cfg, }, + { .compatible = "qcom,sm6150-dpu", .data = &dpu_sm6150_cfg, }, { .compatible = "qcom,sm6350-dpu", .data = &dpu_sm6350_cfg, }, { .compatible = "qcom,sm6375-dpu", .data = &dpu_sm6375_cfg, }, { .compatible = "qcom,sm7150-dpu", .data = &dpu_sm7150_cfg, }, @@ -1487,6 +1534,7 @@ static const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,sm8450-dpu", .data = &dpu_sm8450_cfg, }, { .compatible = "qcom,sm8550-dpu", .data = &dpu_sm8550_cfg, }, { .compatible = "qcom,sm8650-dpu", .data = &dpu_sm8650_cfg, }, + { .compatible = "qcom,sm8750-dpu", .data = &dpu_sm8750_cfg, }, { .compatible = "qcom,x1e80100-dpu", .data = &dpu_x1e80100_cfg, }, {} }; @@ -1494,7 +1542,7 @@ MODULE_DEVICE_TABLE(of, dpu_dt_match); static struct platform_driver dpu_driver = { .probe = dpu_dev_probe, - .remove_new = dpu_dev_remove, + .remove = dpu_dev_remove, .shutdown = msm_kms_shutdown, .driver = { .name = "msm_dpu", diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 88d64d43ea1a..993cf512f8c5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -54,11 +54,13 @@ #define ktime_compare_safe(A, B) \ ktime_compare(ktime_sub((A), (B)), ktime_set(0, 0)) +extern bool dpu_use_virtual_planes; + struct dpu_kms { struct msm_kms base; struct drm_device *dev; const struct dpu_mdss_cfg *catalog; - const struct msm_mdss_data *mdss; + const struct qcom_ubwc_cfg_data *mdss; /* io/register spaces: */ void __iomem *mmio, *vbif[VBIF_MAX]; @@ -122,12 +124,15 @@ struct dpu_global_state { struct dpu_rm *rm; - uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0]; - uint32_t mixer_to_enc_id[LM_MAX - LM_0]; - uint32_t ctl_to_enc_id[CTL_MAX - CTL_0]; - uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0]; - uint32_t dsc_to_enc_id[DSC_MAX - DSC_0]; - uint32_t cdm_to_enc_id; + uint32_t pingpong_to_crtc_id[PINGPONG_MAX - PINGPONG_0]; + uint32_t mixer_to_crtc_id[LM_MAX - LM_0]; + uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0]; + uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0]; + uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0]; + uint32_t cdm_to_crtc_id; + + uint32_t sspp_to_crtc_id[SSPP_MAX - SSPP_NONE]; + uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0]; }; struct dpu_global_state diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 3ffac24333a2..d07a6ab6e7ee 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -17,10 +17,10 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> +#include <linux/soc/qcom/ubwc.h> + #include "msm_drv.h" -#include "msm_mdss.h" #include "dpu_kms.h" -#include "dpu_formats.h" #include "dpu_hw_sspp.h" #include "dpu_hw_util.h" #include "dpu_trace.h" @@ -72,7 +72,7 @@ static const uint32_t qcom_compressed_supported_formats[] = { /* * struct dpu_plane - local dpu plane structure - * @aspace: address space pointer + * @vm: address space pointer * @csc_ptr: Points to dpu_csc_cfg structure to use for current * @catalog: Points to dpu catalog structure * @revalidate: force revalidation of all the plane properties @@ -500,13 +500,15 @@ static void _dpu_plane_setup_pixel_ext(struct dpu_hw_scaler3_cfg *scale_cfg, int i; for (i = 0; i < DPU_MAX_PLANES; i++) { + uint32_t w = src_w, h = src_h; + if (i == DPU_SSPP_COMP_1_2 || i == DPU_SSPP_COMP_2) { - src_w /= chroma_subsmpl_h; - src_h /= chroma_subsmpl_v; + w /= chroma_subsmpl_h; + h /= chroma_subsmpl_v; } - pixel_ext->num_ext_pxls_top[i] = src_h; - pixel_ext->num_ext_pxls_left[i] = src_w; + pixel_ext->num_ext_pxls_top[i] = h; + pixel_ext->num_ext_pxls_left[i] = w; } } @@ -620,6 +622,7 @@ static void _dpu_plane_color_fill(struct dpu_plane *pdpu, struct msm_drm_private *priv = plane->dev->dev_private; struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state); u32 fill_color = (color & 0xFFFFFF) | ((alpha & 0xFF) << 24); + int i; DPU_DEBUG_PLANE(pdpu, "\n"); @@ -633,12 +636,13 @@ static void _dpu_plane_color_fill(struct dpu_plane *pdpu, return; /* update sspp */ - _dpu_plane_color_fill_pipe(pstate, &pstate->pipe, &pstate->pipe_cfg.dst_rect, - fill_color, fmt); - - if (pstate->r_pipe.sspp) - _dpu_plane_color_fill_pipe(pstate, &pstate->r_pipe, &pstate->r_pipe_cfg.dst_rect, + for (i = 0; i < PIPES_PER_PLANE; i++) { + if (!pstate->pipe[i].sspp) + continue; + _dpu_plane_color_fill_pipe(pstate, &pstate->pipe[i], + &pstate->pipe_cfg[i].dst_rect, fill_color, fmt); + } } static int dpu_plane_prepare_fb(struct drm_plane *plane, @@ -647,7 +651,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane, struct drm_framebuffer *fb = new_state->fb; struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane_state *pstate = to_dpu_plane_state(new_state); - struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); int ret; if (!new_state->fb) @@ -655,9 +658,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane, DPU_DEBUG_PLANE(pdpu, "FB[%u]\n", fb->base.id); - /* cache aspace */ - pstate->aspace = kms->base.aspace; - /* * TODO: Need to sort out the msm_framebuffer_prepare() call below so * we can use msm_atomic_prepare_fb() instead of doing the @@ -665,13 +665,10 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane, */ drm_gem_plane_helper_prepare_fb(plane, new_state); - if (pstate->aspace) { - ret = msm_framebuffer_prepare(new_state->fb, - pstate->aspace, pstate->needs_dirtyfb); - if (ret) { - DPU_ERROR("failed to prepare framebuffer\n"); - return ret; - } + ret = msm_framebuffer_prepare(new_state->fb, pstate->needs_dirtyfb); + if (ret) { + DPU_ERROR("failed to prepare framebuffer\n"); + return ret; } return 0; @@ -690,8 +687,7 @@ static void dpu_plane_cleanup_fb(struct drm_plane *plane, DPU_DEBUG_PLANE(pdpu, "FB[%u]\n", old_state->fb->base.id); - msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace, - old_pstate->needs_dirtyfb); + msm_framebuffer_cleanup(old_state->fb, old_pstate->needs_dirtyfb); } static int dpu_plane_check_inline_rotation(struct dpu_plane *pdpu, @@ -730,12 +726,40 @@ static int dpu_plane_check_inline_rotation(struct dpu_plane *pdpu, static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu, struct dpu_sw_pipe *pipe, struct dpu_sw_pipe_cfg *pipe_cfg, - const struct msm_format *fmt, - const struct drm_display_mode *mode) + const struct drm_display_mode *mode, + struct drm_plane_state *new_plane_state) { uint32_t min_src_size; struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); int ret; + const struct msm_format *fmt; + uint32_t supported_rotations; + const struct dpu_sspp_cfg *pipe_hw_caps; + const struct dpu_sspp_sub_blks *sblk; + + pipe_hw_caps = pipe->sspp->cap; + sblk = pipe->sspp->cap->sblk; + + /* + * We already have verified scaling against platform limitations. + * Now check if the SSPP supports scaling at all. + */ + if (!(sblk->scaler_blk.len && pipe->sspp->ops.setup_scaler) && + ((drm_rect_width(&new_plane_state->src) >> 16 != + drm_rect_width(&new_plane_state->dst)) || + (drm_rect_height(&new_plane_state->src) >> 16 != + drm_rect_height(&new_plane_state->dst)))) + return -ERANGE; + + fmt = msm_framebuffer_format(new_plane_state->fb); + + supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0; + + if (pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION)) + supported_rotations |= DRM_MODE_ROTATE_90; + + pipe_cfg->rotation = drm_rotation_simplify(new_plane_state->rotation, + supported_rotations); min_src_size = MSM_FORMAT_IS_YUV(fmt) ? 2 : 1; @@ -800,10 +824,14 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane, struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate; struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state); - struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; - struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; + struct dpu_sw_pipe_cfg *pipe_cfg; + struct dpu_sw_pipe_cfg *r_pipe_cfg; + struct dpu_sw_pipe_cfg init_pipe_cfg; struct drm_rect fb_rect = { 0 }; + const struct drm_display_mode *mode = &crtc_state->adjusted_mode; uint32_t max_linewidth; + u32 num_lm; + int stage_id, num_stages; min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO); max_scale = MAX_DOWNSCALE_RATIO << 16; @@ -826,10 +854,10 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane, return -EINVAL; } - /* state->src is 16.16, src_rect is not */ - drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src); + num_lm = dpu_crtc_get_num_lm(crtc_state); - pipe_cfg->dst_rect = new_plane_state->dst; + /* state->src is 16.16, src_rect is not */ + drm_rect_fp_to_int(&init_pipe_cfg.src_rect, &new_plane_state->src); fb_rect.x2 = new_plane_state->fb->width; fb_rect.y2 = new_plane_state->fb->height; @@ -854,40 +882,161 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane, max_linewidth = pdpu->catalog->caps->max_linewidth; - drm_rect_rotate(&pipe_cfg->src_rect, + drm_rect_rotate(&init_pipe_cfg.src_rect, new_plane_state->fb->width, new_plane_state->fb->height, new_plane_state->rotation); - if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) || - _dpu_plane_calc_clk(&crtc_state->adjusted_mode, pipe_cfg) > max_mdp_clk_rate) { - if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) { - DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n", - DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth); - return -E2BIG; + /* + * We have 1 mixer pair cfg for 1:1:1 and 2:2:1 topology, 2 mixer pair + * configs for left and right half screen in case of 4:4:2 topology. + * But we may have 2 rect to split wide plane that exceeds limit with 1 + * config for 2:2:1. So need to handle both wide plane splitting, and + * two halves of screen splitting for quad-pipe case. Check dest + * rectangle left/right clipping first, then check wide rectangle + * splitting in every half next. + */ + num_stages = (num_lm + 1) / 2; + /* iterate mixer configs for this plane, to separate left/right with the id */ + for (stage_id = 0; stage_id < num_stages; stage_id++) { + struct drm_rect mixer_rect = { + .x1 = stage_id * mode->hdisplay / num_stages, + .y1 = 0, + .x2 = (stage_id + 1) * mode->hdisplay / num_stages, + .y2 = mode->vdisplay + }; + int cfg_idx = stage_id * PIPES_PER_STAGE; + + pipe_cfg = &pstate->pipe_cfg[cfg_idx]; + r_pipe_cfg = &pstate->pipe_cfg[cfg_idx + 1]; + + drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src); + pipe_cfg->dst_rect = new_plane_state->dst; + + DPU_DEBUG_PLANE(pdpu, "checking src " DRM_RECT_FMT + " vs clip window " DRM_RECT_FMT "\n", + DRM_RECT_ARG(&pipe_cfg->src_rect), + DRM_RECT_ARG(&mixer_rect)); + + /* + * If this plane does not fall into mixer rect, check next + * mixer rect. + */ + if (!drm_rect_clip_scaled(&pipe_cfg->src_rect, + &pipe_cfg->dst_rect, + &mixer_rect)) { + memset(pipe_cfg, 0, 2 * sizeof(struct dpu_sw_pipe_cfg)); + + continue; } - *r_pipe_cfg = *pipe_cfg; - pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1; - pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1; - r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2; - r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2; - } else { - memset(r_pipe_cfg, 0, sizeof(*r_pipe_cfg)); - } + pipe_cfg->dst_rect.x1 -= mixer_rect.x1; + pipe_cfg->dst_rect.x2 -= mixer_rect.x1; + + DPU_DEBUG_PLANE(pdpu, "Got clip src:" DRM_RECT_FMT " dst: " DRM_RECT_FMT "\n", + DRM_RECT_ARG(&pipe_cfg->src_rect), DRM_RECT_ARG(&pipe_cfg->dst_rect)); + + /* Split wide rect into 2 rect */ + if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) || + _dpu_plane_calc_clk(mode, pipe_cfg) > max_mdp_clk_rate) { + + if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) { + DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n", + DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth); + return -E2BIG; + } + + memcpy(r_pipe_cfg, pipe_cfg, sizeof(struct dpu_sw_pipe_cfg)); + pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1; + pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1; + r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2; + r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2; + DPU_DEBUG_PLANE(pdpu, "Split wide plane into:" + DRM_RECT_FMT " and " DRM_RECT_FMT "\n", + DRM_RECT_ARG(&pipe_cfg->src_rect), + DRM_RECT_ARG(&r_pipe_cfg->src_rect)); + } else { + memset(r_pipe_cfg, 0, sizeof(struct dpu_sw_pipe_cfg)); + } - drm_rect_rotate_inv(&pipe_cfg->src_rect, - new_plane_state->fb->width, new_plane_state->fb->height, - new_plane_state->rotation); - if (r_pipe_cfg->src_rect.x1 != 0) - drm_rect_rotate_inv(&r_pipe_cfg->src_rect, - new_plane_state->fb->width, new_plane_state->fb->height, + drm_rect_rotate_inv(&pipe_cfg->src_rect, + new_plane_state->fb->width, + new_plane_state->fb->height, new_plane_state->rotation); + if (drm_rect_width(&r_pipe_cfg->src_rect) != 0) + drm_rect_rotate_inv(&r_pipe_cfg->src_rect, + new_plane_state->fb->width, + new_plane_state->fb->height, + new_plane_state->rotation); + } + pstate->needs_qos_remap = drm_atomic_crtc_needs_modeset(crtc_state); return 0; } +static int dpu_plane_is_multirect_capable(struct dpu_hw_sspp *sspp, + struct dpu_sw_pipe_cfg *pipe_cfg, + const struct msm_format *fmt) +{ + if (drm_rect_width(&pipe_cfg->src_rect) != drm_rect_width(&pipe_cfg->dst_rect) || + drm_rect_height(&pipe_cfg->src_rect) != drm_rect_height(&pipe_cfg->dst_rect)) + return false; + + if (pipe_cfg->rotation & DRM_MODE_ROTATE_90) + return false; + + if (MSM_FORMAT_IS_YUV(fmt)) + return false; + + if (!sspp) + return true; + + if (!test_bit(DPU_SSPP_SMART_DMA_V1, &sspp->cap->features) && + !test_bit(DPU_SSPP_SMART_DMA_V2, &sspp->cap->features)) + return false; + + return true; +} + +static int dpu_plane_is_parallel_capable(struct dpu_sw_pipe_cfg *pipe_cfg, + const struct msm_format *fmt, + uint32_t max_linewidth) +{ + if (MSM_FORMAT_IS_UBWC(fmt) && + drm_rect_width(&pipe_cfg->src_rect) > max_linewidth / 2) + return false; + + return true; +} + +static int dpu_plane_is_multirect_parallel_capable(struct dpu_hw_sspp *sspp, + struct dpu_sw_pipe_cfg *pipe_cfg, + const struct msm_format *fmt, + uint32_t max_linewidth) +{ + return dpu_plane_is_multirect_capable(sspp, pipe_cfg, fmt) && + dpu_plane_is_parallel_capable(pipe_cfg, fmt, max_linewidth); +} + +static bool dpu_plane_get_single_pipe_in_stage(struct dpu_plane_state *pstate, + struct dpu_sw_pipe **single_pipe, + struct dpu_sw_pipe_cfg **single_pipe_cfg, + int stage_index) +{ + int pipe_idx; + + pipe_idx = stage_index * PIPES_PER_STAGE; + if (drm_rect_width(&pstate->pipe_cfg[pipe_idx].src_rect) != 0 && + drm_rect_width(&pstate->pipe_cfg[pipe_idx + 1].src_rect) == 0) { + *single_pipe = &pstate->pipe[pipe_idx]; + *single_pipe_cfg = &pstate->pipe_cfg[pipe_idx]; + return true; + } + + return false; +} + static int dpu_plane_atomic_check_sspp(struct drm_plane *plane, struct drm_atomic_state *state, const struct drm_crtc_state *crtc_state) @@ -896,92 +1045,116 @@ static int dpu_plane_atomic_check_sspp(struct drm_plane *plane, drm_atomic_get_new_plane_state(state, plane); struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state); - struct dpu_sw_pipe *pipe = &pstate->pipe; - struct dpu_sw_pipe *r_pipe = &pstate->r_pipe; - const struct msm_format *fmt; - struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; - struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; - uint32_t max_linewidth; - uint32_t supported_rotations; - const struct dpu_sspp_cfg *pipe_hw_caps; - const struct dpu_sspp_sub_blks *sblk; - int ret = 0; - - pipe_hw_caps = pipe->sspp->cap; - sblk = pipe->sspp->cap->sblk; - - /* - * We already have verified scaling against platform limitations. - * Now check if the SSPP supports scaling at all. - */ - if (!sblk->scaler_blk.len && - ((drm_rect_width(&new_plane_state->src) >> 16 != - drm_rect_width(&new_plane_state->dst)) || - (drm_rect_height(&new_plane_state->src) >> 16 != - drm_rect_height(&new_plane_state->dst)))) - return -ERANGE; - - fmt = msm_framebuffer_format(new_plane_state->fb); - - max_linewidth = pdpu->catalog->caps->max_linewidth; + struct dpu_sw_pipe *pipe; + struct dpu_sw_pipe_cfg *pipe_cfg; + int ret = 0, i; + + for (i = 0; i < PIPES_PER_PLANE; i++) { + pipe = &pstate->pipe[i]; + pipe_cfg = &pstate->pipe_cfg[i]; + if (!drm_rect_width(&pipe_cfg->src_rect)) + continue; + DPU_DEBUG_PLANE(pdpu, "pipe %d is in use, validate it\n", i); + ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, + &crtc_state->adjusted_mode, + new_plane_state); + if (ret) + return ret; + } - supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0; + return 0; +} - if (pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION)) - supported_rotations |= DRM_MODE_ROTATE_90; +static bool dpu_plane_try_multirect_parallel(struct dpu_sw_pipe *pipe, struct dpu_sw_pipe_cfg *pipe_cfg, + struct dpu_sw_pipe *r_pipe, struct dpu_sw_pipe_cfg *r_pipe_cfg, + struct dpu_hw_sspp *sspp, const struct msm_format *fmt, + uint32_t max_linewidth) +{ + r_pipe->sspp = NULL; - pipe_cfg->rotation = drm_rotation_simplify(new_plane_state->rotation, - supported_rotations); - r_pipe_cfg->rotation = pipe_cfg->rotation; + pipe->multirect_index = DPU_SSPP_RECT_SOLO; + pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; - ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt, - &crtc_state->adjusted_mode); - if (ret) - return ret; + r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; + r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; if (drm_rect_width(&r_pipe_cfg->src_rect) != 0) { - /* - * In parallel multirect case only the half of the usual width - * is supported for tiled formats. If we are here, we know that - * full width is more than max_linewidth, thus each rect is - * wider than allowed. - */ - if (MSM_FORMAT_IS_UBWC(fmt) && - drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) { - DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u, tiled format\n", - DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth); - return -E2BIG; - } + if (!dpu_plane_is_multirect_parallel_capable(pipe->sspp, pipe_cfg, fmt, max_linewidth) || + !dpu_plane_is_multirect_parallel_capable(pipe->sspp, r_pipe_cfg, fmt, max_linewidth)) + return false; - if (drm_rect_width(&pipe_cfg->src_rect) != drm_rect_width(&pipe_cfg->dst_rect) || - drm_rect_height(&pipe_cfg->src_rect) != drm_rect_height(&pipe_cfg->dst_rect) || - (!test_bit(DPU_SSPP_SMART_DMA_V1, &pipe->sspp->cap->features) && - !test_bit(DPU_SSPP_SMART_DMA_V2, &pipe->sspp->cap->features)) || - pipe_cfg->rotation & DRM_MODE_ROTATE_90 || - MSM_FORMAT_IS_YUV(fmt)) { - DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u, can't use split source\n", - DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth); - return -E2BIG; - } + r_pipe->sspp = pipe->sspp; - /* - * Use multirect for wide plane. We do not support dynamic - * assignment of SSPPs, so we know the configuration. - */ pipe->multirect_index = DPU_SSPP_RECT_0; pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; - r_pipe->sspp = pipe->sspp; r_pipe->multirect_index = DPU_SSPP_RECT_1; r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; + } - ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg, fmt, - &crtc_state->adjusted_mode); - if (ret) - return ret; + return true; +} + +static int dpu_plane_try_multirect_shared(struct dpu_plane_state *pstate, + struct dpu_plane_state *prev_adjacent_pstate, + const struct msm_format *fmt, + uint32_t max_linewidth, int stage_index) +{ + struct dpu_sw_pipe *pipe, *prev_pipe; + struct dpu_sw_pipe_cfg *pipe_cfg, *prev_pipe_cfg; + const struct msm_format *prev_fmt = msm_framebuffer_format(prev_adjacent_pstate->base.fb); + u16 max_tile_height = 1; + + if (!dpu_plane_get_single_pipe_in_stage(pstate, &pipe, + &pipe_cfg, stage_index)) + return false; + + if (!dpu_plane_get_single_pipe_in_stage(prev_adjacent_pstate, + &prev_pipe, &prev_pipe_cfg, + stage_index) || + prev_pipe->multirect_mode != DPU_SSPP_MULTIRECT_NONE) + return false; + + /* Do not validate SSPP of current plane when it is not ready */ + if (!dpu_plane_is_multirect_capable(pipe->sspp, pipe_cfg, fmt) || + !dpu_plane_is_multirect_capable(prev_pipe->sspp, prev_pipe_cfg, prev_fmt)) + return false; + + if (MSM_FORMAT_IS_UBWC(fmt)) + max_tile_height = max(max_tile_height, fmt->tile_height); + + if (MSM_FORMAT_IS_UBWC(prev_fmt)) + max_tile_height = max(max_tile_height, prev_fmt->tile_height); + + if (dpu_plane_is_parallel_capable(pipe_cfg, fmt, max_linewidth) && + dpu_plane_is_parallel_capable(prev_pipe_cfg, prev_fmt, max_linewidth) && + (pipe_cfg->dst_rect.x1 >= prev_pipe_cfg->dst_rect.x2 || + prev_pipe_cfg->dst_rect.x1 >= pipe_cfg->dst_rect.x2)) { + pipe->sspp = prev_pipe->sspp; + + pipe->multirect_index = DPU_SSPP_RECT_1; + pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; + + prev_pipe->multirect_index = DPU_SSPP_RECT_0; + prev_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; + + return true; } - return 0; + if (pipe_cfg->dst_rect.y1 >= prev_pipe_cfg->dst_rect.y2 + 2 * max_tile_height || + prev_pipe_cfg->dst_rect.y1 >= pipe_cfg->dst_rect.y2 + 2 * max_tile_height) { + pipe->sspp = prev_pipe->sspp; + + pipe->multirect_index = DPU_SSPP_RECT_1; + pipe->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX; + + prev_pipe->multirect_index = DPU_SSPP_RECT_0; + prev_pipe->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX; + + return true; + } + + return false; } static int dpu_plane_atomic_check(struct drm_plane *plane, @@ -993,16 +1166,21 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state); struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); - struct dpu_sw_pipe *pipe = &pstate->pipe; - struct dpu_sw_pipe *r_pipe = &pstate->r_pipe; + struct dpu_sw_pipe *pipe = &pstate->pipe[0]; + struct dpu_sw_pipe *r_pipe = &pstate->pipe[1]; + struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg[0]; + struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->pipe_cfg[1]; const struct drm_crtc_state *crtc_state = NULL; + uint32_t max_linewidth = dpu_kms->catalog->caps->max_linewidth; if (new_plane_state->crtc) crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc); pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe); - r_pipe->sspp = NULL; + + if (!pipe->sspp) + return -EINVAL; ret = dpu_plane_atomic_check_nosspp(plane, new_plane_state, crtc_state); if (ret) @@ -1011,14 +1189,197 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, if (!new_plane_state->visible) return 0; + if (!dpu_plane_try_multirect_parallel(pipe, pipe_cfg, r_pipe, r_pipe_cfg, + pipe->sspp, + msm_framebuffer_format(new_plane_state->fb), + max_linewidth)) { + DPU_DEBUG_PLANE(pdpu, "invalid " DRM_RECT_FMT " /" DRM_RECT_FMT + " max_line:%u, can't use split source\n", + DRM_RECT_ARG(&pipe_cfg->src_rect), + DRM_RECT_ARG(&r_pipe_cfg->src_rect), + max_linewidth); + return -E2BIG; + } + + return dpu_plane_atomic_check_sspp(plane, state, crtc_state); +} + +static int dpu_plane_virtual_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct drm_plane_state *plane_state = + drm_atomic_get_plane_state(state, plane); + struct drm_plane_state *old_plane_state = + drm_atomic_get_old_plane_state(state, plane); + struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state); + struct drm_crtc_state *crtc_state = NULL; + int ret, i; + + if (IS_ERR(plane_state)) + return PTR_ERR(plane_state); + + if (plane_state->crtc) + crtc_state = drm_atomic_get_new_crtc_state(state, + plane_state->crtc); + + ret = dpu_plane_atomic_check_nosspp(plane, plane_state, crtc_state); + if (ret) + return ret; + + if (!plane_state->visible) { + /* + * resources are freed by dpu_crtc_assign_plane_resources(), + * but clean them here. + */ + for (i = 0; i < PIPES_PER_PLANE; i++) + pstate->pipe[i].sspp = NULL; + + return 0; + } + + /* + * Force resource reallocation if the format of FB or src/dst have + * changed. We might need to allocate different SSPP or SSPPs for this + * plane than the one used previously. + */ + if (!old_plane_state || !old_plane_state->fb || + old_plane_state->src_w != plane_state->src_w || + old_plane_state->src_h != plane_state->src_h || + old_plane_state->crtc_w != plane_state->crtc_w || + old_plane_state->crtc_h != plane_state->crtc_h || + msm_framebuffer_format(old_plane_state->fb) != + msm_framebuffer_format(plane_state->fb)) + crtc_state->planes_changed = true; + + return 0; +} + +static int dpu_plane_assign_resource_in_stage(struct dpu_sw_pipe *pipe, + struct dpu_sw_pipe_cfg *pipe_cfg, + struct drm_plane_state *plane_state, + struct dpu_global_state *global_state, + struct drm_crtc *crtc, + struct dpu_rm_sspp_requirements *reqs) +{ + struct drm_plane *plane = plane_state->plane; + struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); + struct dpu_sw_pipe *r_pipe = pipe + 1; + struct dpu_sw_pipe_cfg *r_pipe_cfg = pipe_cfg + 1; + + if (drm_rect_width(&pipe_cfg->src_rect) == 0) + return 0; + + pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, reqs); + if (!pipe->sspp) + return -ENODEV; pipe->multirect_index = DPU_SSPP_RECT_SOLO; pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + + if (drm_rect_width(&r_pipe_cfg->src_rect) == 0) + return 0; + + if (dpu_plane_try_multirect_parallel(pipe, pipe_cfg, r_pipe, r_pipe_cfg, + pipe->sspp, + msm_framebuffer_format(plane_state->fb), + dpu_kms->catalog->caps->max_linewidth)) + return 0; + + r_pipe->sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, reqs); + if (!r_pipe->sspp) + return -ENODEV; r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + return 0; +} + +static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc, + struct dpu_global_state *global_state, + struct drm_atomic_state *state, + struct drm_plane_state *plane_state, + struct drm_plane_state **prev_adjacent_plane_state) +{ + const struct drm_crtc_state *crtc_state = NULL; + struct drm_plane *plane = plane_state->plane; + struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); + struct dpu_rm_sspp_requirements reqs; + struct dpu_plane_state *pstate, *prev_adjacent_pstate[STAGES_PER_PLANE]; + struct dpu_sw_pipe *pipe; + struct dpu_sw_pipe_cfg *pipe_cfg; + const struct msm_format *fmt; + int i, ret; + + if (plane_state->crtc) + crtc_state = drm_atomic_get_new_crtc_state(state, + plane_state->crtc); + + pstate = to_dpu_plane_state(plane_state); + for (i = 0; i < STAGES_PER_PLANE; i++) + prev_adjacent_pstate[i] = prev_adjacent_plane_state[i] ? + to_dpu_plane_state(prev_adjacent_plane_state[i]) : NULL; + + for (i = 0; i < PIPES_PER_PLANE; i++) + pstate->pipe[i].sspp = NULL; + + if (!plane_state->fb) + return -EINVAL; + + fmt = msm_framebuffer_format(plane_state->fb); + reqs.yuv = MSM_FORMAT_IS_YUV(fmt); + reqs.scale = (plane_state->src_w >> 16 != plane_state->crtc_w) || + (plane_state->src_h >> 16 != plane_state->crtc_h); + + reqs.rot90 = drm_rotation_90_or_270(plane_state->rotation); + + for (i = 0; i < STAGES_PER_PLANE; i++) { + if (prev_adjacent_pstate[i] && + dpu_plane_try_multirect_shared(pstate, prev_adjacent_pstate[i], fmt, + dpu_kms->catalog->caps->max_linewidth, + i)) + continue; + + if (dpu_plane_get_single_pipe_in_stage(pstate, &pipe, &pipe_cfg, i)) + prev_adjacent_plane_state[i] = plane_state; + + pipe = &pstate->pipe[i * PIPES_PER_STAGE]; + pipe_cfg = &pstate->pipe_cfg[i * PIPES_PER_STAGE]; + ret = dpu_plane_assign_resource_in_stage(pipe, pipe_cfg, + plane_state, + global_state, + crtc, &reqs); + if (ret) + return ret; + } + return dpu_plane_atomic_check_sspp(plane, state, crtc_state); } +int dpu_assign_plane_resources(struct dpu_global_state *global_state, + struct drm_atomic_state *state, + struct drm_crtc *crtc, + struct drm_plane_state **states, + unsigned int num_planes) +{ + unsigned int i; + struct drm_plane_state *prev_adjacent_plane_state[STAGES_PER_PLANE] = { NULL }; + + for (i = 0; i < num_planes; i++) { + struct drm_plane_state *plane_state = states[i]; + + if (!plane_state || + !plane_state->visible) + continue; + + int ret = dpu_plane_virtual_assign_resources(crtc, global_state, + state, plane_state, + prev_adjacent_plane_state); + if (ret) + return ret; + } + + return 0; +} + static void dpu_plane_flush_csc(struct dpu_plane *pdpu, struct dpu_sw_pipe *pipe) { const struct msm_format *format = @@ -1049,6 +1410,7 @@ void dpu_plane_flush(struct drm_plane *plane) { struct dpu_plane *pdpu; struct dpu_plane_state *pstate; + int i; if (!plane || !plane->state) { DPU_ERROR("invalid plane\n"); @@ -1069,8 +1431,8 @@ void dpu_plane_flush(struct drm_plane *plane) /* force 100% alpha */ _dpu_plane_color_fill(pdpu, pdpu->color_fill, 0xFF); else { - dpu_plane_flush_csc(pdpu, &pstate->pipe); - dpu_plane_flush_csc(pdpu, &pstate->r_pipe); + for (i = 0; i < PIPES_PER_PLANE; i++) + dpu_plane_flush_csc(pdpu, &pstate->pipe[i]); } /* flag h/w flush complete */ @@ -1171,15 +1533,12 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane, struct dpu_plane *pdpu = to_dpu_plane(plane); struct drm_plane_state *state = plane->state; struct dpu_plane_state *pstate = to_dpu_plane_state(state); - struct dpu_sw_pipe *pipe = &pstate->pipe; - struct dpu_sw_pipe *r_pipe = &pstate->r_pipe; struct drm_crtc *crtc = state->crtc; struct drm_framebuffer *fb = state->fb; bool is_rt_pipe; const struct msm_format *fmt = msm_framebuffer_format(fb); - struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; - struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; + int i; pstate->pending = true; @@ -1187,19 +1546,18 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane, pstate->needs_qos_remap |= (is_rt_pipe != pdpu->is_rt_pipe); pdpu->is_rt_pipe = is_rt_pipe; - dpu_format_populate_addrs(pstate->aspace, new_state->fb, &pstate->layout); + dpu_format_populate_addrs(new_state->fb, &pstate->layout); DPU_DEBUG_PLANE(pdpu, "FB[%u] " DRM_RECT_FP_FMT "->crtc%u " DRM_RECT_FMT ", %p4cc ubwc %d\n", fb->base.id, DRM_RECT_FP_ARG(&state->src), crtc->base.id, DRM_RECT_ARG(&state->dst), &fmt->pixel_format, MSM_FORMAT_IS_UBWC(fmt)); - dpu_plane_sspp_update_pipe(plane, pipe, pipe_cfg, fmt, - drm_mode_vrefresh(&crtc->mode), - &pstate->layout); - - if (r_pipe->sspp) { - dpu_plane_sspp_update_pipe(plane, r_pipe, r_pipe_cfg, fmt, + for (i = 0; i < PIPES_PER_PLANE; i++) { + if (!drm_rect_width(&pstate->pipe_cfg[i].src_rect)) + continue; + dpu_plane_sspp_update_pipe(plane, &pstate->pipe[i], + &pstate->pipe_cfg[i], fmt, drm_mode_vrefresh(&crtc->mode), &pstate->layout); } @@ -1207,15 +1565,17 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane, if (pstate->needs_qos_remap) pstate->needs_qos_remap = false; - pstate->plane_fetch_bw = _dpu_plane_calc_bw(pdpu->catalog, fmt, - &crtc->mode, pipe_cfg); - - pstate->plane_clk = _dpu_plane_calc_clk(&crtc->mode, pipe_cfg); - - if (r_pipe->sspp) { - pstate->plane_fetch_bw += _dpu_plane_calc_bw(pdpu->catalog, fmt, &crtc->mode, r_pipe_cfg); - - pstate->plane_clk = max(pstate->plane_clk, _dpu_plane_calc_clk(&crtc->mode, r_pipe_cfg)); + pstate->plane_fetch_bw = 0; + pstate->plane_clk = 0; + for (i = 0; i < PIPES_PER_PLANE; i++) { + if (!drm_rect_width(&pstate->pipe_cfg[i].src_rect)) + continue; + pstate->plane_fetch_bw += _dpu_plane_calc_bw(pdpu->catalog, fmt, + &crtc->mode, &pstate->pipe_cfg[i]); + + pstate->plane_clk = max(pstate->plane_clk, + _dpu_plane_calc_clk(&crtc->mode, + &pstate->pipe_cfg[i])); } } @@ -1223,17 +1583,28 @@ static void _dpu_plane_atomic_disable(struct drm_plane *plane) { struct drm_plane_state *state = plane->state; struct dpu_plane_state *pstate = to_dpu_plane_state(state); - struct dpu_sw_pipe *r_pipe = &pstate->r_pipe; + struct dpu_sw_pipe *pipe; + int i; + + for (i = 0; i < PIPES_PER_PLANE; i += 1) { + pipe = &pstate->pipe[i]; + if (!pipe->sspp) + continue; - trace_dpu_plane_disable(DRMID(plane), false, - pstate->pipe.multirect_mode); + trace_dpu_plane_disable(DRMID(plane), false, + pstate->pipe[i].multirect_mode); - if (r_pipe->sspp) { - r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; - r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + if (i % PIPES_PER_STAGE == 0) + continue; - if (r_pipe->sspp->ops.setup_multirect) - r_pipe->sspp->ops.setup_multirect(r_pipe); + /* + * clear multirect for the right pipe so that the SSPP + * can be further reused in the solo mode + */ + pipe->multirect_index = DPU_SSPP_RECT_SOLO; + pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + if (pipe->sspp->ops.setup_multirect) + pipe->sspp->ops.setup_multirect(pipe); } pstate->pending = true; @@ -1328,28 +1699,26 @@ static void dpu_plane_atomic_print_state(struct drm_printer *p, const struct drm_plane_state *state) { const struct dpu_plane_state *pstate = to_dpu_plane_state(state); - const struct dpu_sw_pipe *pipe = &pstate->pipe; - const struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; - const struct dpu_sw_pipe *r_pipe = &pstate->r_pipe; - const struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; + const struct dpu_sw_pipe *pipe; + const struct dpu_sw_pipe_cfg *pipe_cfg; + int i; drm_printf(p, "\tstage=%d\n", pstate->stage); - drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name); - drm_printf(p, "\tmultirect_mode[0]=%s\n", dpu_get_multirect_mode(pipe->multirect_mode)); - drm_printf(p, "\tmultirect_index[0]=%s\n", - dpu_get_multirect_index(pipe->multirect_index)); - drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->src_rect)); - drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->dst_rect)); - - if (r_pipe->sspp) { - drm_printf(p, "\tsspp[1]=%s\n", r_pipe->sspp->cap->name); - drm_printf(p, "\tmultirect_mode[1]=%s\n", - dpu_get_multirect_mode(r_pipe->multirect_mode)); - drm_printf(p, "\tmultirect_index[1]=%s\n", - dpu_get_multirect_index(r_pipe->multirect_index)); - drm_printf(p, "\tsrc[1]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&r_pipe_cfg->src_rect)); - drm_printf(p, "\tdst[1]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&r_pipe_cfg->dst_rect)); + for (i = 0; i < PIPES_PER_PLANE; i++) { + pipe = &pstate->pipe[i]; + if (!pipe->sspp) + continue; + pipe_cfg = &pstate->pipe_cfg[i]; + drm_printf(p, "\tsspp[%d]=%s\n", i, pipe->sspp->cap->name); + drm_printf(p, "\tmultirect_mode[%d]=%s\n", i, + dpu_get_multirect_mode(pipe->multirect_mode)); + drm_printf(p, "\tmultirect_index[%d]=%s\n", i, + dpu_get_multirect_index(pipe->multirect_index)); + drm_printf(p, "\tsrc[%d]=" DRM_RECT_FMT "\n", i, + DRM_RECT_ARG(&pipe_cfg->src_rect)); + drm_printf(p, "\tdst[%d]=" DRM_RECT_FMT "\n", i, + DRM_RECT_ARG(&pipe_cfg->dst_rect)); } } @@ -1387,14 +1756,17 @@ void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state); struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); + int i; if (!pdpu->is_rt_pipe) return; pm_runtime_get_sync(&dpu_kms->pdev->dev); - _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, enable); - if (pstate->r_pipe.sspp) - _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, enable); + for (i = 0; i < PIPES_PER_PLANE; i++) { + if (!pstate->pipe[i].sspp) + continue; + _dpu_plane_set_qos_ctrl(plane, &pstate->pipe[i], enable); + } pm_runtime_put_sync(&dpu_kms->pdev->dev); } #endif @@ -1433,39 +1805,29 @@ static const struct drm_plane_helper_funcs dpu_plane_helper_funcs = { .atomic_update = dpu_plane_atomic_update, }; -/** - * dpu_plane_init - create new dpu plane for the given pipe - * @dev: Pointer to DRM device - * @pipe: dpu hardware pipe identifier - * @type: Plane type - PRIMARY/OVERLAY/CURSOR - * @possible_crtcs: bitmask of crtc that can be attached to the given pipe - * - * Initialize the plane. - */ -struct drm_plane *dpu_plane_init(struct drm_device *dev, - uint32_t pipe, enum drm_plane_type type, - unsigned long possible_crtcs) +static const struct drm_plane_helper_funcs dpu_plane_virtual_helper_funcs = { + .prepare_fb = dpu_plane_prepare_fb, + .cleanup_fb = dpu_plane_cleanup_fb, + .atomic_check = dpu_plane_virtual_atomic_check, + .atomic_update = dpu_plane_atomic_update, +}; + +/* initialize plane */ +static struct drm_plane *dpu_plane_init_common(struct drm_device *dev, + enum drm_plane_type type, + unsigned long possible_crtcs, + bool inline_rotation, + const uint32_t *format_list, + uint32_t num_formats, + enum dpu_sspp pipe) { struct drm_plane *plane = NULL; - const uint32_t *format_list; struct dpu_plane *pdpu; struct msm_drm_private *priv = dev->dev_private; struct dpu_kms *kms = to_dpu_kms(priv->kms); - struct dpu_hw_sspp *pipe_hw; - uint32_t num_formats; uint32_t supported_rotations; int ret; - /* initialize underlying h/w driver */ - pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe); - if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) { - DPU_ERROR("[%u]SSPP is invalid\n", pipe); - return ERR_PTR(-EINVAL); - } - - format_list = pipe_hw->cap->sblk->format_list; - num_formats = pipe_hw->cap->sblk->num_formats; - pdpu = drmm_universal_plane_alloc(dev, struct dpu_plane, base, 0xff, &dpu_plane_funcs, format_list, num_formats, @@ -1491,7 +1853,7 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; - if (pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION)) + if (inline_rotation) supported_rotations |= DRM_MODE_ROTATE_MASK; drm_plane_create_rotation_property(plane, @@ -1499,10 +1861,98 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, drm_plane_enable_fb_damage_clips(plane); - /* success! finalize initialization */ + DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name, + pipe, plane->base.id); + return plane; +} + +/** + * dpu_plane_init - create new dpu plane for the given pipe + * @dev: Pointer to DRM device + * @pipe: dpu hardware pipe identifier + * @type: Plane type - PRIMARY/OVERLAY/CURSOR + * @possible_crtcs: bitmask of crtc that can be attached to the given pipe + * + * Initialize the plane. + */ +struct drm_plane *dpu_plane_init(struct drm_device *dev, + uint32_t pipe, enum drm_plane_type type, + unsigned long possible_crtcs) +{ + struct drm_plane *plane = NULL; + struct msm_drm_private *priv = dev->dev_private; + struct dpu_kms *kms = to_dpu_kms(priv->kms); + struct dpu_hw_sspp *pipe_hw; + + /* initialize underlying h/w driver */ + pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe); + if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) { + DPU_ERROR("[%u]SSPP is invalid\n", pipe); + return ERR_PTR(-EINVAL); + } + + + plane = dpu_plane_init_common(dev, type, possible_crtcs, + pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION), + pipe_hw->cap->sblk->format_list, + pipe_hw->cap->sblk->num_formats, + pipe); + if (IS_ERR(plane)) + return plane; + drm_plane_helper_add(plane, &dpu_plane_helper_funcs); DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name, pipe, plane->base.id); + + return plane; +} + +/** + * dpu_plane_init_virtual - create new virtualized DPU plane + * @dev: Pointer to DRM device + * @type: Plane type - PRIMARY/OVERLAY/CURSOR + * @possible_crtcs: bitmask of crtc that can be attached to the given pipe + * + * Initialize the virtual plane with no backing SSPP / pipe. + */ +struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev, + enum drm_plane_type type, + unsigned long possible_crtcs) +{ + struct drm_plane *plane = NULL; + struct msm_drm_private *priv = dev->dev_private; + struct dpu_kms *kms = to_dpu_kms(priv->kms); + bool has_inline_rotation = false; + const u32 *format_list = NULL; + u32 num_formats = 0; + int i; + + /* Determine the largest configuration that we can implement */ + for (i = 0; i < kms->catalog->sspp_count; i++) { + const struct dpu_sspp_cfg *cfg = &kms->catalog->sspp[i]; + + if (test_bit(DPU_SSPP_INLINE_ROTATION, &cfg->features)) + has_inline_rotation = true; + + if (!format_list || + cfg->sblk->csc_blk.len) { + format_list = cfg->sblk->format_list; + num_formats = cfg->sblk->num_formats; + } + } + + plane = dpu_plane_init_common(dev, type, possible_crtcs, + has_inline_rotation, + format_list, + num_formats, + SSPP_NONE); + if (IS_ERR(plane)) + return plane; + + drm_plane_helper_add(plane, &dpu_plane_virtual_helper_funcs); + + DPU_DEBUG("%s created virtual id:%u\n", plane->name, plane->base.id); + return plane; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h index 97090ca7842b..1ef5a041b8ac 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h @@ -17,11 +17,8 @@ /** * struct dpu_plane_state: Define dpu extension of drm plane state object * @base: base drm plane state object - * @aspace: pointer to address space for input/output buffers - * @pipe: software pipe description - * @r_pipe: software pipe description of the second pipe - * @pipe_cfg: software pipe configuration - * @r_pipe_cfg: software pipe configuration for the second pipe + * @pipe: software pipe description array + * @pipe_cfg: software pipe configuration array * @stage: assigned by crtc blender * @needs_qos_remap: qos remap settings need to be updated * @multirect_index: index of the rectangle of SSPP @@ -34,11 +31,8 @@ */ struct dpu_plane_state { struct drm_plane_state base; - struct msm_gem_address_space *aspace; - struct dpu_sw_pipe pipe; - struct dpu_sw_pipe r_pipe; - struct dpu_sw_pipe_cfg pipe_cfg; - struct dpu_sw_pipe_cfg r_pipe_cfg; + struct dpu_sw_pipe pipe[PIPES_PER_PLANE]; + struct dpu_sw_pipe_cfg pipe_cfg[PIPES_PER_PLANE]; enum dpu_stage stage; bool needs_qos_remap; bool pending; @@ -62,10 +56,23 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, uint32_t pipe, enum drm_plane_type type, unsigned long possible_crtcs); +struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev, + enum drm_plane_type type, + unsigned long possible_crtcs); + +int dpu_plane_color_fill(struct drm_plane *plane, + uint32_t color, uint32_t alpha); + #ifdef CONFIG_DEBUG_FS void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable); #else static inline void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) {} #endif +int dpu_assign_plane_resources(struct dpu_global_state *global_state, + struct drm_atomic_state *state, + struct drm_crtc *crtc, + struct drm_plane_state **states, + unsigned int num_planes); + #endif /* _DPU_PLANE_H_ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index c247af03dc8e..f6568ed8375f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s] " fmt, __func__ @@ -9,6 +9,7 @@ #include "dpu_hw_lm.h" #include "dpu_hw_ctl.h" #include "dpu_hw_cdm.h" +#include "dpu_hw_cwb.h" #include "dpu_hw_pingpong.h" #include "dpu_hw_sspp.h" #include "dpu_hw_intf.h" @@ -21,20 +22,12 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx, - uint32_t enc_id) + uint32_t crtc_id) { - return res_map[idx] && res_map[idx] != enc_id; + return res_map[idx] && res_map[idx] != crtc_id; } /** - * struct dpu_rm_requirements - Reservation requirements parameter bundle - * @topology: selected topology for the display - */ -struct dpu_rm_requirements { - struct msm_display_topology topology; -}; - -/** * dpu_rm_init - Read hardware catalog and create reservation tracking objects * for all HW blocks. * @dev: Corresponding device for devres management @@ -47,7 +40,7 @@ struct dpu_rm_requirements { int dpu_rm_init(struct drm_device *dev, struct dpu_rm *rm, const struct dpu_mdss_cfg *cat, - const struct msm_mdss_data *mdss_data, + const struct qcom_ubwc_cfg_data *mdss_data, void __iomem *mmio) { int rc, i; @@ -60,12 +53,14 @@ int dpu_rm_init(struct drm_device *dev, /* Clear, setup lists */ memset(rm, 0, sizeof(*rm)); + rm->has_legacy_ctls = (cat->mdss_ver->core_major_ver < 5); + /* Interrogate HW catalog and create tracking items for hw blocks */ for (i = 0; i < cat->mixer_count; i++) { struct dpu_hw_mixer *hw; const struct dpu_lm_cfg *lm = &cat->mixer[i]; - hw = dpu_hw_lm_init(dev, lm, mmio); + hw = dpu_hw_lm_init(dev, lm, mmio, cat->mdss_ver); if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed lm object creation: err %d\n", rc); @@ -130,11 +125,24 @@ int dpu_rm_init(struct drm_device *dev, rm->hw_wb[wb->id - WB_0] = hw; } + for (i = 0; i < cat->cwb_count; i++) { + struct dpu_hw_cwb *hw; + const struct dpu_cwb_cfg *cwb = &cat->cwb[i]; + + hw = dpu_hw_cwb_init(dev, cwb, mmio); + if (IS_ERR(hw)) { + rc = PTR_ERR(hw); + DPU_ERROR("failed cwb object creation: err %d\n", rc); + goto fail; + } + rm->cwb_blks[cwb->id - CWB_0] = &hw->base; + } + for (i = 0; i < cat->ctl_count; i++) { struct dpu_hw_ctl *hw; const struct dpu_ctl_cfg *ctl = &cat->ctl[i]; - hw = dpu_hw_ctl_init(dev, ctl, mmio, cat->mixer_count, cat->mixer); + hw = dpu_hw_ctl_init(dev, ctl, mmio, cat->mdss_ver, cat->mixer_count, cat->mixer); if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed ctl object creation: err %d\n", rc); @@ -160,10 +168,10 @@ int dpu_rm_init(struct drm_device *dev, struct dpu_hw_dsc *hw; const struct dpu_dsc_cfg *dsc = &cat->dsc[i]; - if (test_bit(DPU_DSC_HW_REV_1_2, &dsc->features)) + if (cat->mdss_ver->core_major_ver >= 7) hw = dpu_hw_dsc_init_1_2(dev, dsc, mmio); else - hw = dpu_hw_dsc_init(dev, dsc, mmio); + hw = dpu_hw_dsc_init(dev, dsc, mmio, cat->mdss_ver); if (IS_ERR(hw)) { rc = PTR_ERR(hw); @@ -227,13 +235,66 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx) return -EINVAL; } +static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm, + struct dpu_global_state *global_state, + uint32_t crtc_id, + struct msm_display_topology *topology) +{ + int num_cwb_mux = topology->num_lm, cwb_mux_count = 0; + int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0; + int cwb_pp_idx[MAX_BLOCKS]; + int cwb_mux_idx[MAX_BLOCKS]; + + /* + * Reserve additional dedicated CWB PINGPONG blocks and muxes for each + * mixer + * + * TODO: add support reserving resources for platforms with no + * PINGPONG_CWB + */ + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) && + cwb_mux_count < num_cwb_mux; i++) { + for (int j = 0; j < ARRAY_SIZE(rm->cwb_blks); j++) { + /* + * Odd LMs must be assigned to odd CWB muxes and even + * LMs with even CWB muxes. + * + * Since the RM HW block array index is based on the HW + * block ids, we can also use the array index to enforce + * the odd/even rule. See dpu_rm_init() for more + * information + */ + if (reserved_by_other(global_state->cwb_to_crtc_id, j, crtc_id) || + i % 2 != j % 2) + continue; + + cwb_mux_idx[cwb_mux_count] = j; + cwb_pp_idx[cwb_mux_count] = j + cwb_pp_start_idx; + cwb_mux_count++; + break; + } + } + + if (cwb_mux_count != num_cwb_mux) { + DPU_ERROR("Unable to reserve all CWB PINGPONGs\n"); + return -ENAVAIL; + } + + for (int i = 0; i < cwb_mux_count; i++) { + global_state->pingpong_to_crtc_id[cwb_pp_idx[i]] = crtc_id; + global_state->cwb_to_crtc_id[cwb_mux_idx[i]] = crtc_id; + } + + return 0; +} + /** * _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets * proposed use case requirements, incl. hardwired dependent blocks like * pingpong * @rm: dpu resource manager handle * @global_state: resources shared across multiple kms objects - * @enc_id: encoder id requesting for allocation + * @crtc_id: crtc id requesting for allocation * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks * if lm, and all other hardwired blocks connected to the lm (pp) is * available and appropriate @@ -241,20 +302,19 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx) * mixer in rm->pingpong_blks[]. * @dspp_idx: output parameter, index of dspp block attached to the layer * mixer in rm->dspp_blks[]. - * @reqs: input parameter, rm requirements for HW blocks needed in the - * datapath. + * @topology: selected topology for the display * Return: true if lm matches all requirements, false otherwise */ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, struct dpu_global_state *global_state, - uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx, - struct dpu_rm_requirements *reqs) + uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx, + struct msm_display_topology *topology) { const struct dpu_lm_cfg *lm_cfg; int idx; /* Already reserved? */ - if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) { + if (reserved_by_other(global_state->mixer_to_crtc_id, lm_idx, crtc_id)) { DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0); return false; } @@ -266,14 +326,14 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, return false; } - if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) { + if (reserved_by_other(global_state->pingpong_to_crtc_id, idx, crtc_id)) { DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id, lm_cfg->pingpong); return false; } *pp_idx = idx; - if (!reqs->topology.num_dspp) + if (!topology->num_dspp) return true; idx = lm_cfg->dspp - DSPP_0; @@ -282,7 +342,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, return false; } - if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) { + if (reserved_by_other(global_state->dspp_to_crtc_id, idx, crtc_id)) { DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id, lm_cfg->dspp); return false; @@ -294,8 +354,8 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, static int _dpu_rm_reserve_lms(struct dpu_rm *rm, struct dpu_global_state *global_state, - uint32_t enc_id, - struct dpu_rm_requirements *reqs) + uint32_t crtc_id, + struct msm_display_topology *topology) { int lm_idx[MAX_BLOCKS]; @@ -303,30 +363,34 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, int dspp_idx[MAX_BLOCKS] = {0}; int i, lm_count = 0; - if (!reqs->topology.num_lm) { - DPU_ERROR("invalid number of lm: %d\n", reqs->topology.num_lm); + if (!topology->num_lm) { + DPU_ERROR("invalid number of lm: %d\n", topology->num_lm); return -EINVAL; } /* Find a primary mixer */ for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) && - lm_count < reqs->topology.num_lm; i++) { + lm_count < topology->num_lm; i++) { if (!rm->mixer_blks[i]) continue; - lm_count = 0; + /* + * Reset lm_count to an even index. This will drop the previous + * primary mixer if failed to find its peer. + */ + lm_count &= ~1; lm_idx[lm_count] = i; if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state, - enc_id, i, &pp_idx[lm_count], - &dspp_idx[lm_count], reqs)) { + crtc_id, i, &pp_idx[lm_count], + &dspp_idx[lm_count], topology)) { continue; } ++lm_count; /* Valid primary mixer found, find matching peers */ - if (lm_count < reqs->topology.num_lm) { + if (lm_count < topology->num_lm) { int j = _dpu_rm_get_lm_peer(rm, i); /* ignore the peer if there is an error or if the peer was already processed */ @@ -337,9 +401,9 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, continue; if (!_dpu_rm_check_lm_and_get_connected_blks(rm, - global_state, enc_id, j, + global_state, crtc_id, j, &pp_idx[lm_count], &dspp_idx[lm_count], - reqs)) { + topology)) { continue; } @@ -348,18 +412,18 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, } } - if (lm_count != reqs->topology.num_lm) { + if (lm_count != topology->num_lm) { DPU_DEBUG("unable to find appropriate mixers\n"); return -ENAVAIL; } for (i = 0; i < lm_count; i++) { - global_state->mixer_to_enc_id[lm_idx[i]] = enc_id; - global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id; - global_state->dspp_to_enc_id[dspp_idx[i]] = - reqs->topology.num_dspp ? enc_id : 0; + global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id; + global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id; + global_state->dspp_to_crtc_id[dspp_idx[i]] = + topology->num_dspp ? crtc_id : 0; - trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id, + trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, crtc_id, pp_idx[i] + PINGPONG_0); } @@ -369,17 +433,26 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, static int _dpu_rm_reserve_ctls( struct dpu_rm *rm, struct dpu_global_state *global_state, - uint32_t enc_id, + uint32_t crtc_id, const struct msm_display_topology *top) { int ctl_idx[MAX_BLOCKS]; int i = 0, j, num_ctls; bool needs_split_display; - /* each hw_intf needs its own hw_ctrl to program its control path */ - num_ctls = top->num_intf; - - needs_split_display = _dpu_rm_needs_split_display(top); + if (rm->has_legacy_ctls) { + /* + * TODO: check if there is a need for special handling if + * DPU < 5.0 get CWB support. + */ + num_ctls = top->num_intf; + + needs_split_display = _dpu_rm_needs_split_display(top); + } else { + /* use single CTL */ + num_ctls = 1; + needs_split_display = false; + } for (j = 0; j < ARRAY_SIZE(rm->ctl_blks); j++) { const struct dpu_hw_ctl *ctl; @@ -388,7 +461,7 @@ static int _dpu_rm_reserve_ctls( if (!rm->ctl_blks[j]) continue; - if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id)) + if (reserved_by_other(global_state->ctl_to_crtc_id, j, crtc_id)) continue; ctl = to_dpu_hw_ctl(rm->ctl_blks[j]); @@ -412,8 +485,8 @@ static int _dpu_rm_reserve_ctls( return -ENAVAIL; for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) { - global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id; - trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id); + global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id; + trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id); } return 0; @@ -421,12 +494,12 @@ static int _dpu_rm_reserve_ctls( static int _dpu_rm_pingpong_next_index(struct dpu_global_state *global_state, int start, - uint32_t enc_id) + uint32_t crtc_id) { int i; for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) { - if (global_state->pingpong_to_enc_id[i] == enc_id) + if (global_state->pingpong_to_crtc_id[i] == crtc_id) return i; } @@ -447,7 +520,7 @@ static int _dpu_rm_pingpong_dsc_check(int dsc_idx, int pp_idx) static int _dpu_rm_dsc_alloc(struct dpu_rm *rm, struct dpu_global_state *global_state, - uint32_t enc_id, + uint32_t crtc_id, const struct msm_display_topology *top) { int num_dsc = 0; @@ -460,10 +533,10 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm, if (!rm->dsc_blks[dsc_idx]) continue; - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id)) + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id)) continue; - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id); + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id); if (pp_idx < 0) return -ENAVAIL; @@ -471,7 +544,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm, if (ret) return -ENAVAIL; - global_state->dsc_to_enc_id[dsc_idx] = enc_id; + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id; num_dsc++; pp_idx++; } @@ -487,7 +560,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm, static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm, struct dpu_global_state *global_state, - uint32_t enc_id, + uint32_t crtc_id, const struct msm_display_topology *top) { int num_dsc = 0; @@ -502,11 +575,11 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm, continue; /* consective dsc index to be paired */ - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id) || - reserved_by_other(global_state->dsc_to_enc_id, dsc_idx + 1, enc_id)) + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id) || + reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx + 1, crtc_id)) continue; - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id); + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id); if (pp_idx < 0) return -ENAVAIL; @@ -516,7 +589,7 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm, continue; } - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, enc_id); + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, crtc_id); if (pp_idx < 0) return -ENAVAIL; @@ -526,8 +599,8 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm, continue; } - global_state->dsc_to_enc_id[dsc_idx] = enc_id; - global_state->dsc_to_enc_id[dsc_idx + 1] = enc_id; + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id; + global_state->dsc_to_crtc_id[dsc_idx + 1] = crtc_id; num_dsc += 2; pp_idx++; /* start for next pair */ } @@ -543,11 +616,9 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm, static int _dpu_rm_reserve_dsc(struct dpu_rm *rm, struct dpu_global_state *global_state, - struct drm_encoder *enc, + uint32_t crtc_id, const struct msm_display_topology *top) { - uint32_t enc_id = enc->base.id; - if (!top->num_dsc || !top->num_intf) return 0; @@ -563,16 +634,17 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm, /* num_dsc should be either 1, 2 or 4 */ if (top->num_dsc > top->num_intf) /* merge mode */ - return _dpu_rm_dsc_alloc_pair(rm, global_state, enc_id, top); + return _dpu_rm_dsc_alloc_pair(rm, global_state, crtc_id, top); else - return _dpu_rm_dsc_alloc(rm, global_state, enc_id, top); + return _dpu_rm_dsc_alloc(rm, global_state, crtc_id, top); return 0; } static int _dpu_rm_reserve_cdm(struct dpu_rm *rm, struct dpu_global_state *global_state, - struct drm_encoder *enc) + uint32_t crtc_id, + int num_cdm) { /* try allocating only one CDM block */ if (!rm->cdm_blk) { @@ -580,12 +652,17 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm, return -EIO; } - if (global_state->cdm_to_enc_id) { + if (num_cdm > 1) { + DPU_ERROR("More than 1 INTF requesting CDM\n"); + return -EINVAL; + } + + if (global_state->cdm_to_crtc_id) { DPU_ERROR("CDM_0 is already allocated\n"); return -EIO; } - global_state->cdm_to_enc_id = enc->base.id; + global_state->cdm_to_crtc_id = crtc_id; return 0; } @@ -593,30 +670,37 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm, static int _dpu_rm_make_reservation( struct dpu_rm *rm, struct dpu_global_state *global_state, - struct drm_encoder *enc, - struct dpu_rm_requirements *reqs) + uint32_t crtc_id, + struct msm_display_topology *topology) { int ret; - ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, reqs); + ret = _dpu_rm_reserve_lms(rm, global_state, crtc_id, topology); if (ret) { DPU_ERROR("unable to find appropriate mixers\n"); return ret; } - ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id, - &reqs->topology); + if (topology->cwb_enabled) { + ret = _dpu_rm_reserve_cwb_mux_and_pingpongs(rm, global_state, + crtc_id, topology); + if (ret) + return ret; + } + + ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id, + topology); if (ret) { DPU_ERROR("unable to find appropriate CTL\n"); return ret; } - ret = _dpu_rm_reserve_dsc(rm, global_state, enc, &reqs->topology); + ret = _dpu_rm_reserve_dsc(rm, global_state, crtc_id, topology); if (ret) return ret; - if (reqs->topology.needs_cdm) { - ret = _dpu_rm_reserve_cdm(rm, global_state, enc); + if (topology->num_cdm > 0) { + ret = _dpu_rm_reserve_cdm(rm, global_state, crtc_id, topology->num_cdm); if (ret) { DPU_ERROR("unable to find CDM blk\n"); return ret; @@ -626,27 +710,13 @@ static int _dpu_rm_make_reservation( return ret; } -static int _dpu_rm_populate_requirements( - struct drm_encoder *enc, - struct dpu_rm_requirements *reqs, - struct msm_display_topology req_topology) -{ - reqs->topology = req_topology; - - DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d cdm: %d\n", - reqs->topology.num_lm, reqs->topology.num_dsc, - reqs->topology.num_intf, reqs->topology.needs_cdm); - - return 0; -} - static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt, - uint32_t enc_id) + uint32_t crtc_id) { int i; for (i = 0; i < cnt; i++) { - if (res_mapping[i] == enc_id) + if (res_mapping[i] == crtc_id) res_mapping[i] = 0; } } @@ -655,23 +725,27 @@ static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt, * dpu_rm_release - Given the encoder for the display chain, release any * HW blocks previously reserved for that use case. * @global_state: resources shared across multiple kms objects - * @enc: DRM Encoder handle + * @crtc: DRM CRTC handle * @return: 0 on Success otherwise -ERROR */ void dpu_rm_release(struct dpu_global_state *global_state, - struct drm_encoder *enc) + struct drm_crtc *crtc) { - _dpu_rm_clear_mapping(global_state->pingpong_to_enc_id, - ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id); - _dpu_rm_clear_mapping(global_state->mixer_to_enc_id, - ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id); - _dpu_rm_clear_mapping(global_state->ctl_to_enc_id, - ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id); - _dpu_rm_clear_mapping(global_state->dsc_to_enc_id, - ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id); - _dpu_rm_clear_mapping(global_state->dspp_to_enc_id, - ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id); - _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id); + uint32_t crtc_id = crtc->base.id; + + _dpu_rm_clear_mapping(global_state->pingpong_to_crtc_id, + ARRAY_SIZE(global_state->pingpong_to_crtc_id), crtc_id); + _dpu_rm_clear_mapping(global_state->mixer_to_crtc_id, + ARRAY_SIZE(global_state->mixer_to_crtc_id), crtc_id); + _dpu_rm_clear_mapping(global_state->ctl_to_crtc_id, + ARRAY_SIZE(global_state->ctl_to_crtc_id), crtc_id); + _dpu_rm_clear_mapping(global_state->dsc_to_crtc_id, + ARRAY_SIZE(global_state->dsc_to_crtc_id), crtc_id); + _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id, + ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id); + _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id); + _dpu_rm_clear_mapping(global_state->cwb_to_crtc_id, + ARRAY_SIZE(global_state->cwb_to_crtc_id), crtc_id); } /** @@ -683,97 +757,189 @@ void dpu_rm_release(struct dpu_global_state *global_state, * HW Reservations should be released via dpu_rm_release_hw. * @rm: DPU Resource Manager handle * @global_state: resources shared across multiple kms objects - * @enc: DRM Encoder handle - * @crtc_state: Proposed Atomic DRM CRTC State handle + * @crtc: DRM CRTC handle * @topology: Pointer to topology info for the display * @return: 0 on Success otherwise -ERROR */ int dpu_rm_reserve( struct dpu_rm *rm, struct dpu_global_state *global_state, - struct drm_encoder *enc, - struct drm_crtc_state *crtc_state, - struct msm_display_topology topology) + struct drm_crtc *crtc, + struct msm_display_topology *topology) { - struct dpu_rm_requirements reqs; int ret; - /* Check if this is just a page-flip */ - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return 0; - if (IS_ERR(global_state)) { DPU_ERROR("failed to global state\n"); return PTR_ERR(global_state); } - DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n", - enc->base.id, crtc_state->crtc->base.id); + DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id); - ret = _dpu_rm_populate_requirements(enc, &reqs, topology); - if (ret) { - DPU_ERROR("failed to populate hw requirements\n"); - return ret; - } + DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n", + topology->num_lm, topology->num_dsc, + topology->num_intf); - ret = _dpu_rm_make_reservation(rm, global_state, enc, &reqs); + ret = _dpu_rm_make_reservation(rm, global_state, crtc->base.id, topology); if (ret) DPU_ERROR("failed to reserve hw resources: %d\n", ret); + return ret; +} +static struct dpu_hw_sspp *dpu_rm_try_sspp(struct dpu_rm *rm, + struct dpu_global_state *global_state, + struct drm_crtc *crtc, + struct dpu_rm_sspp_requirements *reqs, + unsigned int type) +{ + uint32_t crtc_id = crtc->base.id; + struct dpu_hw_sspp *hw_sspp; + int i; - return ret; + for (i = 0; i < ARRAY_SIZE(rm->hw_sspp); i++) { + if (!rm->hw_sspp[i]) + continue; + + if (global_state->sspp_to_crtc_id[i]) + continue; + + hw_sspp = rm->hw_sspp[i]; + + if (hw_sspp->cap->type != type) + continue; + + if (reqs->scale && !hw_sspp->cap->sblk->scaler_blk.len) + continue; + + // TODO: QSEED2 and RGB scalers are not yet supported + if (reqs->scale && !hw_sspp->ops.setup_scaler) + continue; + + if (reqs->yuv && !hw_sspp->cap->sblk->csc_blk.len) + continue; + + if (reqs->rot90 && !(hw_sspp->cap->features & DPU_SSPP_INLINE_ROTATION)) + continue; + + global_state->sspp_to_crtc_id[i] = crtc_id; + + return rm->hw_sspp[i]; + } + + return NULL; } /** + * dpu_rm_reserve_sspp - Reserve the required SSPP for the provided CRTC + * @rm: DPU Resource Manager handle + * @global_state: private global state + * @crtc: DRM CRTC handle + * @reqs: SSPP required features + */ +struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm, + struct dpu_global_state *global_state, + struct drm_crtc *crtc, + struct dpu_rm_sspp_requirements *reqs) +{ + struct dpu_hw_sspp *hw_sspp = NULL; + + if (!reqs->scale && !reqs->yuv) + hw_sspp = dpu_rm_try_sspp(rm, global_state, crtc, reqs, SSPP_TYPE_DMA); + if (!hw_sspp && !reqs->yuv) + hw_sspp = dpu_rm_try_sspp(rm, global_state, crtc, reqs, SSPP_TYPE_RGB); + if (!hw_sspp) + hw_sspp = dpu_rm_try_sspp(rm, global_state, crtc, reqs, SSPP_TYPE_VIG); + + return hw_sspp; +} + +/** + * dpu_rm_release_all_sspp - Given the CRTC, release all SSPP + * blocks previously reserved for that use case. + * @global_state: resources shared across multiple kms objects + * @crtc: DRM CRTC handle + */ +void dpu_rm_release_all_sspp(struct dpu_global_state *global_state, + struct drm_crtc *crtc) +{ + uint32_t crtc_id = crtc->base.id; + + _dpu_rm_clear_mapping(global_state->sspp_to_crtc_id, + ARRAY_SIZE(global_state->sspp_to_crtc_id), crtc_id); +} + +static char *dpu_hw_blk_type_name[] = { + [DPU_HW_BLK_TOP] = "TOP", + [DPU_HW_BLK_SSPP] = "SSPP", + [DPU_HW_BLK_LM] = "LM", + [DPU_HW_BLK_CTL] = "CTL", + [DPU_HW_BLK_PINGPONG] = "pingpong", + [DPU_HW_BLK_INTF] = "INTF", + [DPU_HW_BLK_WB] = "WB", + [DPU_HW_BLK_DSPP] = "DSPP", + [DPU_HW_BLK_MERGE_3D] = "merge_3d", + [DPU_HW_BLK_DSC] = "DSC", + [DPU_HW_BLK_CDM] = "CDM", + [DPU_HW_BLK_MAX] = "unknown", +}; + +/** * dpu_rm_get_assigned_resources - Get hw resources of the given type that are * assigned to this encoder * @rm: DPU Resource Manager handle * @global_state: resources shared across multiple kms objects - * @enc_id: encoder id requesting for allocation + * @crtc: DRM CRTC handle * @type: resource type to return data for * @blks: pointer to the array to be filled by HW resources * @blks_size: size of the @blks array */ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, - struct dpu_global_state *global_state, uint32_t enc_id, + struct dpu_global_state *global_state, struct drm_crtc *crtc, enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size) { + uint32_t crtc_id = crtc->base.id; struct dpu_hw_blk **hw_blks; - uint32_t *hw_to_enc_id; + uint32_t *hw_to_crtc_id; int i, num_blks, max_blks; switch (type) { case DPU_HW_BLK_PINGPONG: + case DPU_HW_BLK_DCWB_PINGPONG: hw_blks = rm->pingpong_blks; - hw_to_enc_id = global_state->pingpong_to_enc_id; + hw_to_crtc_id = global_state->pingpong_to_crtc_id; max_blks = ARRAY_SIZE(rm->pingpong_blks); break; case DPU_HW_BLK_LM: hw_blks = rm->mixer_blks; - hw_to_enc_id = global_state->mixer_to_enc_id; + hw_to_crtc_id = global_state->mixer_to_crtc_id; max_blks = ARRAY_SIZE(rm->mixer_blks); break; case DPU_HW_BLK_CTL: hw_blks = rm->ctl_blks; - hw_to_enc_id = global_state->ctl_to_enc_id; + hw_to_crtc_id = global_state->ctl_to_crtc_id; max_blks = ARRAY_SIZE(rm->ctl_blks); break; case DPU_HW_BLK_DSPP: hw_blks = rm->dspp_blks; - hw_to_enc_id = global_state->dspp_to_enc_id; + hw_to_crtc_id = global_state->dspp_to_crtc_id; max_blks = ARRAY_SIZE(rm->dspp_blks); break; case DPU_HW_BLK_DSC: hw_blks = rm->dsc_blks; - hw_to_enc_id = global_state->dsc_to_enc_id; + hw_to_crtc_id = global_state->dsc_to_crtc_id; max_blks = ARRAY_SIZE(rm->dsc_blks); break; case DPU_HW_BLK_CDM: hw_blks = &rm->cdm_blk; - hw_to_enc_id = &global_state->cdm_to_enc_id; + hw_to_crtc_id = &global_state->cdm_to_crtc_id; max_blks = 1; break; + case DPU_HW_BLK_CWB: + hw_blks = rm->cwb_blks; + hw_to_crtc_id = global_state->cwb_to_crtc_id; + max_blks = ARRAY_SIZE(rm->cwb_blks); + break; default: DPU_ERROR("blk type %d not managed by rm\n", type); return 0; @@ -781,17 +947,31 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, num_blks = 0; for (i = 0; i < max_blks; i++) { - if (hw_to_enc_id[i] != enc_id) + if (hw_to_crtc_id[i] != crtc_id) continue; + if (type == DPU_HW_BLK_PINGPONG) { + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]); + + if (pp->idx >= PINGPONG_CWB_0) + continue; + } + + if (type == DPU_HW_BLK_DCWB_PINGPONG) { + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]); + + if (pp->idx < PINGPONG_CWB_0) + continue; + } + if (num_blks == blks_size) { - DPU_ERROR("More than %d resources assigned to enc %d\n", - blks_size, enc_id); + DPU_ERROR("More than %d %s assigned to crtc %d\n", + blks_size, dpu_hw_blk_type_name[type], crtc_id); break; } if (!hw_blks[i]) { - DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n", - type, enc_id); + DPU_ERROR("%s unavailable to assign to crtc %d\n", + dpu_hw_blk_type_name[type], crtc_id); break; } blks[num_blks++] = hw_blks[i]; @@ -826,37 +1006,50 @@ void dpu_rm_print_state(struct drm_printer *p, drm_puts(p, "resource mapping:\n"); drm_puts(p, "\tpingpong="); - for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++) + for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_crtc_id); i++) dpu_rm_print_state_helper(p, rm->pingpong_blks[i], - global_state->pingpong_to_enc_id[i]); + global_state->pingpong_to_crtc_id[i]); drm_puts(p, "\n"); drm_puts(p, "\tmixer="); - for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++) + for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_crtc_id); i++) dpu_rm_print_state_helper(p, rm->mixer_blks[i], - global_state->mixer_to_enc_id[i]); + global_state->mixer_to_crtc_id[i]); drm_puts(p, "\n"); drm_puts(p, "\tctl="); - for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++) + for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_crtc_id); i++) dpu_rm_print_state_helper(p, rm->ctl_blks[i], - global_state->ctl_to_enc_id[i]); + global_state->ctl_to_crtc_id[i]); drm_puts(p, "\n"); drm_puts(p, "\tdspp="); - for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++) + for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_crtc_id); i++) dpu_rm_print_state_helper(p, rm->dspp_blks[i], - global_state->dspp_to_enc_id[i]); + global_state->dspp_to_crtc_id[i]); drm_puts(p, "\n"); drm_puts(p, "\tdsc="); - for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++) + for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_crtc_id); i++) dpu_rm_print_state_helper(p, rm->dsc_blks[i], - global_state->dsc_to_enc_id[i]); + global_state->dsc_to_crtc_id[i]); drm_puts(p, "\n"); drm_puts(p, "\tcdm="); dpu_rm_print_state_helper(p, rm->cdm_blk, - global_state->cdm_to_enc_id); + global_state->cdm_to_crtc_id); + drm_puts(p, "\n"); + + drm_puts(p, "\tsspp="); + /* skip SSPP_NONE and start from the next index */ + for (i = SSPP_NONE + 1; i < ARRAY_SIZE(global_state->sspp_to_crtc_id); i++) + dpu_rm_print_state_helper(p, rm->hw_sspp[i] ? &rm->hw_sspp[i]->base : NULL, + global_state->sspp_to_crtc_id[i]); + drm_puts(p, "\n"); + + drm_puts(p, "\tcwb="); + for (i = 0; i < ARRAY_SIZE(global_state->cwb_to_crtc_id); i++) + dpu_rm_print_state_helper(p, rm->cwb_blks[i], + global_state->cwb_to_crtc_id[i]); drm_puts(p, "\n"); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h index ea0e49cb7b0d..ccd64404f12d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h @@ -20,9 +20,11 @@ struct dpu_global_state; * @ctl_blks: array of ctl hardware resources * @hw_intf: array of intf hardware resources * @hw_wb: array of wb hardware resources + * @hw_cwb: array of cwb hardware resources * @dspp_blks: array of dspp hardware resources * @hw_sspp: array of sspp hardware resources * @cdm_blk: cdm hardware resource + * @has_legacy_ctls: DPU uses pre-ACTIVE CTL blocks. */ struct dpu_rm { struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0]; @@ -30,11 +32,19 @@ struct dpu_rm { struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0]; struct dpu_hw_intf *hw_intf[INTF_MAX - INTF_0]; struct dpu_hw_wb *hw_wb[WB_MAX - WB_0]; + struct dpu_hw_blk *cwb_blks[CWB_MAX - CWB_0]; struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0]; struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0]; struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0]; struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE]; struct dpu_hw_blk *cdm_blk; + bool has_legacy_ctls; +}; + +struct dpu_rm_sspp_requirements { + bool yuv; + bool scale; + bool rot90; }; /** @@ -43,33 +53,43 @@ struct dpu_rm { * @num_intf: number of interfaces the panel is mounted on * @num_dspp: number of dspp blocks used * @num_dsc: number of Display Stream Compression (DSC) blocks used - * @needs_cdm: indicates whether cdm block is needed for this display topology + * @num_cdm: indicates how many outputs are requesting cdm block for + * this display topology + * @cwb_enabled: indicates whether CWB is enabled for this display topology */ struct msm_display_topology { u32 num_lm; u32 num_intf; u32 num_dspp; u32 num_dsc; - bool needs_cdm; + int num_cdm; + bool cwb_enabled; }; int dpu_rm_init(struct drm_device *dev, struct dpu_rm *rm, const struct dpu_mdss_cfg *cat, - const struct msm_mdss_data *mdss_data, + const struct qcom_ubwc_cfg_data *mdss_data, void __iomem *mmio); int dpu_rm_reserve(struct dpu_rm *rm, struct dpu_global_state *global_state, - struct drm_encoder *drm_enc, - struct drm_crtc_state *crtc_state, - struct msm_display_topology topology); + struct drm_crtc *crtc, + struct msm_display_topology *topology); void dpu_rm_release(struct dpu_global_state *global_state, - struct drm_encoder *enc); + struct drm_crtc *crtc); + +struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm, + struct dpu_global_state *global_state, + struct drm_crtc *crtc, + struct dpu_rm_sspp_requirements *reqs); + +void dpu_rm_release_all_sspp(struct dpu_global_state *global_state, + struct drm_crtc *crtc); int dpu_rm_get_assigned_resources(struct dpu_rm *rm, - struct dpu_global_state *global_state, uint32_t enc_id, + struct dpu_global_state *global_state, struct drm_crtc *crtc, enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size); void dpu_rm_print_state(struct drm_printer *p, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h index 5307cbc2007c..cb24ad2a6d8d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h @@ -651,9 +651,9 @@ TRACE_EVENT(dpu_crtc_setup_mixer, TP_PROTO(uint32_t crtc_id, uint32_t plane_id, struct drm_plane_state *state, struct dpu_plane_state *pstate, uint32_t stage_idx, uint32_t pixel_format, - uint64_t modifier), + struct dpu_sw_pipe *pipe, uint64_t modifier), TP_ARGS(crtc_id, plane_id, state, pstate, stage_idx, - pixel_format, modifier), + pixel_format, pipe, modifier), TP_STRUCT__entry( __field( uint32_t, crtc_id ) __field( uint32_t, plane_id ) @@ -676,9 +676,9 @@ TRACE_EVENT(dpu_crtc_setup_mixer, __entry->dst_rect = drm_plane_state_dest(state); __entry->stage_idx = stage_idx; __entry->stage = pstate->stage; - __entry->sspp = pstate->pipe.sspp->idx; - __entry->multirect_idx = pstate->pipe.multirect_index; - __entry->multirect_mode = pstate->pipe.multirect_mode; + __entry->sspp = pipe->sspp->idx; + __entry->multirect_idx = pipe->multirect_index; + __entry->multirect_mode = pipe->multirect_mode; __entry->pixel_format = pixel_format; __entry->modifier = modifier; ), diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c index 16f144cbc0c9..7545c0293efb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c @@ -42,9 +42,6 @@ static int dpu_wb_conn_atomic_check(struct drm_connector *connector, if (!conn_state || !conn_state->connector) { DPU_ERROR("invalid connector state\n"); return -EINVAL; - } else if (conn_state->connector->status != connector_status_connected) { - DPU_ERROR("connector not connected %d\n", conn_state->connector->status); - return -EINVAL; } crtc = conn_state->crtc; @@ -75,6 +72,9 @@ static int dpu_wb_conn_atomic_check(struct drm_connector *connector, DPU_ERROR("invalid fb w=%d, maxlinewidth=%u\n", fb->width, dpu_wb_conn->maxlinewidth); return -EINVAL; + } else if (fb->modifier != DRM_FORMAT_MOD_LINEAR) { + DPU_ERROR("unsupported fb modifier:%#llx\n", fb->modifier); + return -EINVAL; } return drm_atomic_helper_check_wb_connector_state(conn_state->connector, conn_state->state); @@ -83,7 +83,6 @@ static int dpu_wb_conn_atomic_check(struct drm_connector *connector, static const struct drm_connector_funcs dpu_wb_conn_funcs = { .reset = drm_atomic_helper_connector_reset, .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; @@ -134,12 +133,9 @@ int dpu_writeback_init(struct drm_device *dev, struct drm_encoder *enc, drm_connector_helper_add(&dpu_wb_conn->base.base, &dpu_wb_conn_helper_funcs); - /* DPU initializes the encoder and sets it up completely for writeback - * cases and hence should use the new API drm_writeback_connector_init_with_encoder - * to initialize the writeback connector - */ - rc = drm_writeback_connector_init_with_encoder(dev, &dpu_wb_conn->base, enc, - &dpu_wb_conn_funcs, format_list, num_formats); + rc = drmm_writeback_connector_init(dev, &dpu_wb_conn->base, + &dpu_wb_conn_funcs, enc, + format_list, num_formats); if (!rc) dpu_wb_conn->wb_enc = enc; diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c index b8610aa806ea..e8066f9fd534 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c @@ -17,7 +17,6 @@ struct mdp4_crtc { struct drm_crtc base; char name[8]; - int id; int ovlp; enum mdp4_dma dma; bool enabled; @@ -120,7 +119,7 @@ static void unref_cursor_worker(struct drm_flip_work *work, void *val) struct mdp4_kms *mdp4_kms = get_kms(&mdp4_crtc->base); struct msm_kms *kms = &mdp4_kms->base.base; - msm_gem_unpin_iova(val, kms->aspace); + msm_gem_unpin_iova(val, kms->vm); drm_gem_object_put(val); } @@ -369,7 +368,7 @@ static void update_cursor(struct drm_crtc *crtc) if (next_bo) { /* take a obj ref + iova ref when we start scanning out: */ drm_gem_object_get(next_bo); - msm_gem_get_and_pin_iova(next_bo, kms->aspace, &iova); + msm_gem_get_and_pin_iova(next_bo, kms->vm, &iova); /* enable cursor: */ mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_SIZE(dma), @@ -427,7 +426,7 @@ static int mdp4_crtc_cursor_set(struct drm_crtc *crtc, } if (cursor_bo) { - ret = msm_gem_get_and_pin_iova(cursor_bo, kms->aspace, &iova); + ret = msm_gem_get_and_pin_iova(cursor_bo, kms->vm, &iova); if (ret) goto fail; } else { @@ -511,7 +510,7 @@ static void mdp4_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus) if (pending & PENDING_CURSOR) { update_cursor(crtc); - drm_flip_work_commit(&mdp4_crtc->unref_cursor_work, priv->wq); + drm_flip_work_commit(&mdp4_crtc->unref_cursor_work, priv->kms->wq); } } @@ -528,18 +527,19 @@ static void mdp4_crtc_wait_for_flush_done(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); struct mdp4_kms *mdp4_kms = get_kms(crtc); + wait_queue_head_t *queue = drm_crtc_vblank_waitqueue(crtc); int ret; ret = drm_crtc_vblank_get(crtc); if (ret) return; - ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue, + ret = wait_event_timeout(*queue, !(mdp4_read(mdp4_kms, REG_MDP4_OVERLAY_FLUSH) & mdp4_crtc->flushed_mask), msecs_to_jiffies(50)); if (ret <= 0) - dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp4_crtc->id); + dev_warn(dev->dev, "vblank time out, crtc=%s\n", mdp4_crtc->base.name); mdp4_crtc->flushed_mask = 0; @@ -624,7 +624,7 @@ static void mdp4_crtc_flip_cleanup(struct drm_device *dev, void *ptr) /* initialize crtc */ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, - struct drm_plane *plane, int id, int ovlp_id, + struct drm_plane *plane, int ovlp_id, enum mdp4_dma dma_id) { struct drm_crtc *crtc = NULL; @@ -639,8 +639,6 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, crtc = &mdp4_crtc->base; - mdp4_crtc->id = id; - mdp4_crtc->ovlp = ovlp_id; mdp4_crtc->dma = dma_id; diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index 6e4e74f9d63d..809ca191e9de 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -6,6 +6,8 @@ #include <linux/delay.h> +#include <drm/drm_bridge.h> +#include <drm/drm_bridge_connector.h> #include <drm/drm_vblank.h> #include "msm_drv.h" @@ -120,15 +122,16 @@ static void mdp4_destroy(struct msm_kms *kms) { struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); struct device *dev = mdp4_kms->dev->dev; - struct msm_gem_address_space *aspace = kms->aspace; if (mdp4_kms->blank_cursor_iova) - msm_gem_unpin_iova(mdp4_kms->blank_cursor_bo, kms->aspace); + msm_gem_unpin_iova(mdp4_kms->blank_cursor_bo, kms->vm); drm_gem_object_put(mdp4_kms->blank_cursor_bo); - if (aspace) { - aspace->mmu->funcs->detach(aspace->mmu); - msm_gem_address_space_put(aspace); + if (kms->vm) { + struct msm_mmu *mmu = to_msm_vm(kms->vm)->mmu; + + mmu->funcs->detach(mmu); + drm_gpuvm_put(kms->vm); } if (mdp4_kms->rpm_enabled) @@ -189,7 +192,7 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, struct msm_drm_private *priv = dev->dev_private; struct drm_encoder *encoder; struct drm_connector *connector; - struct device_node *panel_node; + struct drm_bridge *next_bridge; int dsi_id; int ret; @@ -199,27 +202,43 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, * bail out early if there is no panel node (no need to * initialize LCDC encoder and LVDS connector) */ - panel_node = of_graph_get_remote_node(dev->dev->of_node, 0, 0); - if (!panel_node) - return 0; + next_bridge = devm_drm_of_get_bridge(dev->dev, dev->dev->of_node, 0, 0); + if (IS_ERR(next_bridge)) { + ret = PTR_ERR(next_bridge); + if (ret == -ENODEV) + return 0; + return ret; + } - encoder = mdp4_lcdc_encoder_init(dev, panel_node); + encoder = mdp4_lcdc_encoder_init(dev); if (IS_ERR(encoder)) { DRM_DEV_ERROR(dev->dev, "failed to construct LCDC encoder\n"); - of_node_put(panel_node); return PTR_ERR(encoder); } /* LCDC can be hooked to DMA_P (TODO: Add DMA_S later?) */ encoder->possible_crtcs = 1 << DMA_P; - connector = mdp4_lvds_connector_init(dev, panel_node, encoder); + ret = drm_bridge_attach(encoder, next_bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret) { + DRM_DEV_ERROR(dev->dev, "failed to attach LVDS panel/bridge: %d\n", ret); + + return ret; + } + + connector = drm_bridge_connector_init(dev, encoder); if (IS_ERR(connector)) { DRM_DEV_ERROR(dev->dev, "failed to initialize LVDS connector\n"); - of_node_put(panel_node); return PTR_ERR(connector); } + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + DRM_DEV_ERROR(dev->dev, "failed to attach LVDS connector: %d\n", ret); + + return ret; + } + break; case DRM_MODE_ENCODER_TMDS: encoder = mdp4_dtv_encoder_init(dev); @@ -231,9 +250,9 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, /* DTV can be hooked to DMA_E: */ encoder->possible_crtcs = 1 << 1; - if (priv->hdmi) { + if (priv->kms->hdmi) { /* Construct bridge/connector for HDMI: */ - ret = msm_hdmi_modeset_init(priv->hdmi, dev, encoder); + ret = msm_hdmi_modeset_init(priv->kms->hdmi, dev, encoder); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to initialize HDMI: %d\n", ret); return ret; @@ -245,7 +264,7 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, /* only DSI1 supported for now */ dsi_id = 0; - if (!priv->dsi[dsi_id]) + if (!priv->kms->dsi[dsi_id]) break; encoder = mdp4_dsi_encoder_init(dev); @@ -259,7 +278,7 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, /* TODO: Add DMA_S later? */ encoder->possible_crtcs = 1 << DMA_P; - ret = msm_dsi_modeset_init(priv->dsi[dsi_id], dev, encoder); + ret = msm_dsi_modeset_init(priv->kms->dsi[dsi_id], dev, encoder); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to initialize DSI: %d\n", ret); @@ -278,7 +297,6 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, static int modeset_init(struct mdp4_kms *mdp4_kms) { struct drm_device *dev = mdp4_kms->dev; - struct msm_drm_private *priv = dev->dev_private; struct drm_plane *plane; struct drm_crtc *crtc; int i, ret; @@ -320,7 +338,7 @@ static int modeset_init(struct mdp4_kms *mdp4_kms) goto fail; } - crtc = mdp4_crtc_init(dev, plane, priv->num_crtcs, i, + crtc = mdp4_crtc_init(dev, plane, i, mdp4_crtcs[i]); if (IS_ERR(crtc)) { DRM_DEV_ERROR(dev->dev, "failed to construct crtc for %s\n", @@ -328,8 +346,6 @@ static int modeset_init(struct mdp4_kms *mdp4_kms) ret = PTR_ERR(crtc); goto fail; } - - priv->num_crtcs++; } /* @@ -375,12 +391,10 @@ static void read_mdp_hw_revision(struct mdp4_kms *mdp4_kms, 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 = to_mdp4_kms(to_mdp_kms(priv->kms)); struct msm_kms *kms = NULL; - struct msm_mmu *mmu; - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; int ret; u32 major, minor; unsigned long max_clk; @@ -442,28 +456,14 @@ static int mdp4_kms_init(struct drm_device *dev) mdp4_disable(mdp4_kms); mdelay(16); - mmu = msm_iommu_new(&pdev->dev, 0); - if (IS_ERR(mmu)) { - ret = PTR_ERR(mmu); + vm = msm_kms_init_vm(mdp4_kms->dev, NULL); + if (IS_ERR(vm)) { + ret = PTR_ERR(vm); goto fail; - } else if (!mmu) { - DRM_DEV_INFO(dev->dev, "no iommu, fallback to phys " - "contig buffers for scanout\n"); - aspace = NULL; - } else { - aspace = msm_gem_address_space_create(mmu, - "mdp4", 0x1000, 0x100000000 - 0x1000); - - if (IS_ERR(aspace)) { - if (!IS_ERR(mmu)) - mmu->funcs->destroy(mmu); - ret = PTR_ERR(aspace); - goto fail; - } - - kms->aspace = aspace; } + kms->vm = vm; + ret = modeset_init(mdp4_kms); if (ret) { DRM_DEV_ERROR(dev->dev, "modeset_init failed: %d\n", ret); @@ -478,7 +478,7 @@ static int mdp4_kms_init(struct drm_device *dev) goto fail; } - ret = msm_gem_get_and_pin_iova(mdp4_kms->blank_cursor_bo, kms->aspace, + ret = msm_gem_get_and_pin_iova(mdp4_kms->blank_cursor_bo, kms->vm, &mdp4_kms->blank_cursor_iova); if (ret) { DRM_DEV_ERROR(dev->dev, "could not pin blank-cursor bo: %d\n", ret); @@ -512,7 +512,7 @@ static int mdp4_probe(struct platform_device *pdev) mdp4_kms = devm_kzalloc(dev, sizeof(*mdp4_kms), GFP_KERNEL); if (!mdp4_kms) - return dev_err_probe(dev, -ENOMEM, "failed to allocate kms\n"); + return -ENOMEM; mdp4_kms->mmio = msm_ioremap(pdev, NULL); if (IS_ERR(mdp4_kms->mmio)) @@ -568,7 +568,7 @@ MODULE_DEVICE_TABLE(of, mdp4_dt_match); static struct platform_driver mdp4_platform_driver = { .probe = mdp4_probe, - .remove_new = mdp4_remove, + .remove = mdp4_remove, .shutdown = msm_kms_shutdown, .driver = { .name = "mdp4", diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h index 94b1ba92785f..06458d4ee48c 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h @@ -185,18 +185,13 @@ void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config); void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer); void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc); struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, - struct drm_plane *plane, int id, int ovlp_id, + struct drm_plane *plane, int ovlp_id, enum mdp4_dma dma_id); long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate); struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev); -long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate); -struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, - struct device_node *panel_node); - -struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev, - struct device_node *panel_node, struct drm_encoder *encoder); +struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev); #ifdef CONFIG_DRM_MSM_DSI struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev); @@ -207,13 +202,6 @@ static inline struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev) } #endif -#ifdef CONFIG_COMMON_CLK -struct clk *mpd4_lvds_pll_init(struct drm_device *dev); -#else -static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev) -{ - return ERR_PTR(-ENODEV); -} -#endif +struct clk *mdp4_get_lcdc_clock(struct drm_device *dev); #endif /* __MDP4_KMS_H__ */ diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c index 576995ddce37..1051873057f6 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c @@ -14,7 +14,6 @@ struct mdp4_lcdc_encoder { struct drm_encoder base; - struct device_node *panel_node; struct drm_panel *panel; struct clk *lcdc_clk; unsigned long int pixclock; @@ -262,19 +261,12 @@ static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); struct mdp4_kms *mdp4_kms = get_kms(encoder); - struct drm_panel *panel; if (WARN_ON(!mdp4_lcdc_encoder->enabled)) return; mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0); - panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); - if (!IS_ERR(panel)) { - drm_panel_disable(panel); - drm_panel_unprepare(panel); - } - /* * Wait for a vsync so we know the ENABLE=0 latched before * the (connector) source of the vsync's gets disabled, @@ -300,7 +292,6 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) to_mdp4_lcdc_encoder(encoder); unsigned long pc = mdp4_lcdc_encoder->pixclock; struct mdp4_kms *mdp4_kms = get_kms(encoder); - struct drm_panel *panel; uint32_t config; int ret; @@ -335,12 +326,6 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) if (ret) DRM_DEV_ERROR(dev->dev, "failed to enable lcdc_clk: %d\n", ret); - panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); - if (!IS_ERR(panel)) { - drm_panel_prepare(panel); - drm_panel_enable(panel); - } - setup_phy(encoder); mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1); @@ -348,22 +333,34 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) mdp4_lcdc_encoder->enabled = true; } +static enum drm_mode_status +mdp4_lcdc_encoder_mode_valid(struct drm_encoder *encoder, + const struct drm_display_mode *mode) +{ + struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = + to_mdp4_lcdc_encoder(encoder); + long actual, requested; + + requested = 1000 * mode->clock; + actual = clk_round_rate(mdp4_lcdc_encoder->lcdc_clk, requested); + + DBG("requested=%ld, actual=%ld", requested, actual); + + if (actual != requested) + return MODE_CLOCK_RANGE; + + return MODE_OK; +} + static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = { .mode_set = mdp4_lcdc_encoder_mode_set, .disable = mdp4_lcdc_encoder_disable, .enable = mdp4_lcdc_encoder_enable, + .mode_valid = mdp4_lcdc_encoder_mode_valid, }; -long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate) -{ - struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = - to_mdp4_lcdc_encoder(encoder); - return clk_round_rate(mdp4_lcdc_encoder->lcdc_clk, rate); -} - /* initialize encoder */ -struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, - struct device_node *panel_node) +struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev) { struct drm_encoder *encoder; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder; @@ -374,14 +371,11 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, if (IS_ERR(mdp4_lcdc_encoder)) return ERR_CAST(mdp4_lcdc_encoder); - mdp4_lcdc_encoder->panel_node = panel_node; - encoder = &mdp4_lcdc_encoder->base; drm_encoder_helper_add(encoder, &mdp4_lcdc_encoder_helper_funcs); - /* TODO: do we need different pll in other cases? */ - mdp4_lcdc_encoder->lcdc_clk = mpd4_lvds_pll_init(dev); + mdp4_lcdc_encoder->lcdc_clk = mdp4_get_lcdc_clock(dev); if (IS_ERR(mdp4_lcdc_encoder->lcdc_clk)) { DRM_DEV_ERROR(dev->dev, "failed to get lvds_clk\n"); return ERR_CAST(mdp4_lcdc_encoder->lcdc_clk); @@ -389,7 +383,7 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, /* TODO: different regulators in other cases? */ mdp4_lcdc_encoder->regs[0].supply = "lvds-vccs-3p3v"; - mdp4_lcdc_encoder->regs[1].supply = "lvds-vccs-3p3v"; + mdp4_lcdc_encoder->regs[1].supply = "lvds-pll-vdda"; mdp4_lcdc_encoder->regs[2].supply = "lvds-vdda"; ret = devm_regulator_bulk_get(dev->dev, diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c deleted file mode 100644 index 7444b75c4215..000000000000 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c +++ /dev/null @@ -1,121 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2014 Red Hat - * Author: Rob Clark <robdclark@gmail.com> - * Author: Vinay Simha <vinaysimha@inforcecomputing.com> - */ - -#include "mdp4_kms.h" - -struct mdp4_lvds_connector { - struct drm_connector base; - struct drm_encoder *encoder; - struct device_node *panel_node; - struct drm_panel *panel; -}; -#define to_mdp4_lvds_connector(x) container_of(x, struct mdp4_lvds_connector, base) - -static enum drm_connector_status mdp4_lvds_connector_detect( - struct drm_connector *connector, bool force) -{ - struct mdp4_lvds_connector *mdp4_lvds_connector = - to_mdp4_lvds_connector(connector); - - if (!mdp4_lvds_connector->panel) { - mdp4_lvds_connector->panel = - of_drm_find_panel(mdp4_lvds_connector->panel_node); - if (IS_ERR(mdp4_lvds_connector->panel)) - mdp4_lvds_connector->panel = NULL; - } - - return mdp4_lvds_connector->panel ? - connector_status_connected : - connector_status_disconnected; -} - -static void mdp4_lvds_connector_destroy(struct drm_connector *connector) -{ - struct mdp4_lvds_connector *mdp4_lvds_connector = - to_mdp4_lvds_connector(connector); - - drm_connector_cleanup(connector); - - kfree(mdp4_lvds_connector); -} - -static int mdp4_lvds_connector_get_modes(struct drm_connector *connector) -{ - struct mdp4_lvds_connector *mdp4_lvds_connector = - to_mdp4_lvds_connector(connector); - struct drm_panel *panel = mdp4_lvds_connector->panel; - int ret = 0; - - if (panel) - ret = drm_panel_get_modes(panel, connector); - - return ret; -} - -static enum drm_mode_status -mdp4_lvds_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct mdp4_lvds_connector *mdp4_lvds_connector = - to_mdp4_lvds_connector(connector); - struct drm_encoder *encoder = mdp4_lvds_connector->encoder; - long actual, requested; - - requested = 1000 * mode->clock; - actual = mdp4_lcdc_round_pixclk(encoder, requested); - - DBG("requested=%ld, actual=%ld", requested, actual); - - if (actual != requested) - return MODE_CLOCK_RANGE; - - return MODE_OK; -} - -static const struct drm_connector_funcs mdp4_lvds_connector_funcs = { - .detect = mdp4_lvds_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = mdp4_lvds_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -static const struct drm_connector_helper_funcs mdp4_lvds_connector_helper_funcs = { - .get_modes = mdp4_lvds_connector_get_modes, - .mode_valid = mdp4_lvds_connector_mode_valid, -}; - -/* initialize connector */ -struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev, - struct device_node *panel_node, struct drm_encoder *encoder) -{ - struct drm_connector *connector = NULL; - struct mdp4_lvds_connector *mdp4_lvds_connector; - - mdp4_lvds_connector = kzalloc(sizeof(*mdp4_lvds_connector), GFP_KERNEL); - if (!mdp4_lvds_connector) - return ERR_PTR(-ENOMEM); - - mdp4_lvds_connector->encoder = encoder; - mdp4_lvds_connector->panel_node = panel_node; - - connector = &mdp4_lvds_connector->base; - - drm_connector_init(dev, connector, &mdp4_lvds_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - drm_connector_helper_add(connector, &mdp4_lvds_connector_helper_funcs); - - connector->polled = 0; - - connector->interlace_allowed = 0; - connector->doublescan_allowed = 0; - - drm_connector_attach_encoder(connector, encoder); - - return connector; -} diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c index ab8c0c187fb2..04c49bf3d854 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_pll.c @@ -54,7 +54,7 @@ static const struct pll_rate *find_rate(unsigned long rate) return &freqtbl[i-1]; } -static int mpd4_lvds_pll_enable(struct clk_hw *hw) +static int mdp4_lvds_pll_enable(struct clk_hw *hw) { struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw); struct mdp4_kms *mdp4_kms = get_kms(lvds_pll); @@ -80,7 +80,7 @@ static int mpd4_lvds_pll_enable(struct clk_hw *hw) return 0; } -static void mpd4_lvds_pll_disable(struct clk_hw *hw) +static void mdp4_lvds_pll_disable(struct clk_hw *hw) { struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw); struct mdp4_kms *mdp4_kms = get_kms(lvds_pll); @@ -91,21 +91,24 @@ static void mpd4_lvds_pll_disable(struct clk_hw *hw) mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_PLL_CTRL_0, 0x0); } -static unsigned long mpd4_lvds_pll_recalc_rate(struct clk_hw *hw, +static unsigned long mdp4_lvds_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw); return lvds_pll->pixclk; } -static long mpd4_lvds_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int mdp4_lvds_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - const struct pll_rate *pll_rate = find_rate(rate); - return pll_rate->rate; + const struct pll_rate *pll_rate = find_rate(req->rate); + + req->rate = pll_rate->rate; + + return 0; } -static int mpd4_lvds_pll_set_rate(struct clk_hw *hw, unsigned long rate, +static int mdp4_lvds_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw); @@ -114,48 +117,67 @@ static int mpd4_lvds_pll_set_rate(struct clk_hw *hw, unsigned long rate, } -static const struct clk_ops mpd4_lvds_pll_ops = { - .enable = mpd4_lvds_pll_enable, - .disable = mpd4_lvds_pll_disable, - .recalc_rate = mpd4_lvds_pll_recalc_rate, - .round_rate = mpd4_lvds_pll_round_rate, - .set_rate = mpd4_lvds_pll_set_rate, +static const struct clk_ops mdp4_lvds_pll_ops = { + .enable = mdp4_lvds_pll_enable, + .disable = mdp4_lvds_pll_disable, + .recalc_rate = mdp4_lvds_pll_recalc_rate, + .determine_rate = mdp4_lvds_pll_determine_rate, + .set_rate = mdp4_lvds_pll_set_rate, }; -static const char *mpd4_lvds_pll_parents[] = { - "pxo", +static const struct clk_parent_data mdp4_lvds_pll_parents[] = { + { .fw_name = "pxo", .name = "pxo", }, }; static struct clk_init_data pll_init = { - .name = "mpd4_lvds_pll", - .ops = &mpd4_lvds_pll_ops, - .parent_names = mpd4_lvds_pll_parents, - .num_parents = ARRAY_SIZE(mpd4_lvds_pll_parents), + .name = "mdp4_lvds_pll", + .ops = &mdp4_lvds_pll_ops, + .parent_data = mdp4_lvds_pll_parents, + .num_parents = ARRAY_SIZE(mdp4_lvds_pll_parents), }; -struct clk *mpd4_lvds_pll_init(struct drm_device *dev) +static struct clk_hw *mdp4_lvds_pll_init(struct drm_device *dev) { struct mdp4_lvds_pll *lvds_pll; - struct clk *clk; int ret; lvds_pll = devm_kzalloc(dev->dev, sizeof(*lvds_pll), GFP_KERNEL); - if (!lvds_pll) { - ret = -ENOMEM; - goto fail; - } + if (!lvds_pll) + return ERR_PTR(-ENOMEM); lvds_pll->dev = dev; lvds_pll->pll_hw.init = &pll_init; - clk = devm_clk_register(dev->dev, &lvds_pll->pll_hw); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - goto fail; + ret = devm_clk_hw_register(dev->dev, &lvds_pll->pll_hw); + if (ret) + return ERR_PTR(ret); + + ret = devm_of_clk_add_hw_provider(dev->dev, of_clk_hw_simple_get, &lvds_pll->pll_hw); + if (ret) + return ERR_PTR(ret); + + return &lvds_pll->pll_hw; +} + +struct clk *mdp4_get_lcdc_clock(struct drm_device *dev) +{ + struct clk_hw *hw; + struct clk *clk; + + + /* TODO: do we need different pll in other cases? */ + hw = mdp4_lvds_pll_init(dev); + if (IS_ERR(hw)) { + DRM_DEV_ERROR(dev->dev, "failed to register LVDS PLL\n"); + return ERR_CAST(hw); } - return clk; + clk = devm_clk_get(dev->dev, "lcdc_clk"); + if (clk == ERR_PTR(-ENOENT)) { + drm_warn(dev, "can't get LCDC clock, using PLL directly\n"); + + return devm_clk_hw_get_clk(dev->dev, hw, "lcdc_clk"); + } -fail: - return ERR_PTR(ret); + return clk; } diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c index 3fefb2088008..098c3b5ff2b2 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c @@ -79,30 +79,25 @@ static const struct drm_plane_funcs mdp4_plane_funcs = { static int mdp4_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { - struct msm_drm_private *priv = plane->dev->dev_private; - struct msm_kms *kms = priv->kms; - if (!new_state->fb) return 0; drm_gem_plane_helper_prepare_fb(plane, new_state); - return msm_framebuffer_prepare(new_state->fb, kms->aspace, false); + return msm_framebuffer_prepare(new_state->fb, false); } static void mdp4_plane_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state) { struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); - struct mdp4_kms *mdp4_kms = get_kms(plane); - struct msm_kms *kms = &mdp4_kms->base.base; struct drm_framebuffer *fb = old_state->fb; if (!fb) return; DBG("%s: cleanup: FB[%u]", mdp4_plane->name, fb->base.id); - msm_framebuffer_cleanup(fb, kms->aspace, false); + msm_framebuffer_cleanup(fb, false); } @@ -141,7 +136,6 @@ static void mdp4_plane_set_scanout(struct drm_plane *plane, { struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); struct mdp4_kms *mdp4_kms = get_kms(plane); - struct msm_kms *kms = &mdp4_kms->base.base; enum mdp4_pipe pipe = mdp4_plane->pipe; mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_A(pipe), @@ -153,13 +147,13 @@ static void mdp4_plane_set_scanout(struct drm_plane *plane, MDP4_PIPE_SRC_STRIDE_B_P3(fb->pitches[3])); mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe), - msm_framebuffer_iova(fb, kms->aspace, 0)); + msm_framebuffer_iova(fb, 0)); mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP1_BASE(pipe), - msm_framebuffer_iova(fb, kms->aspace, 1)); + msm_framebuffer_iova(fb, 1)); mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP2_BASE(pipe), - msm_framebuffer_iova(fb, kms->aspace, 2)); + msm_framebuffer_iova(fb, 2)); mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP3_BASE(pipe), - msm_framebuffer_iova(fb, kms->aspace, 3)); + msm_framebuffer_iova(fb, 3)); } static void mdp4_write_csc_config(struct mdp4_kms *mdp4_kms, diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c index 0f653e62b4a0..373ae7d9bf01 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -169,7 +169,7 @@ static void unref_cursor_worker(struct drm_flip_work *work, void *val) struct mdp5_kms *mdp5_kms = get_kms(&mdp5_crtc->base); struct msm_kms *kms = &mdp5_kms->base.base; - msm_gem_unpin_iova(val, kms->aspace); + msm_gem_unpin_iova(val, kms->vm); drm_gem_object_put(val); } @@ -993,7 +993,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, if (!cursor_bo) return -ENOENT; - ret = msm_gem_get_and_pin_iova(cursor_bo, kms->aspace, + ret = msm_gem_get_and_pin_iova(cursor_bo, kms->vm, &mdp5_crtc->cursor.iova); if (ret) { drm_gem_object_put(cursor_bo); @@ -1196,7 +1196,7 @@ static void mdp5_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus) } if (pending & PENDING_CURSOR) - drm_flip_work_commit(&mdp5_crtc->unref_cursor_work, priv->wq); + drm_flip_work_commit(&mdp5_crtc->unref_cursor_work, priv->kms->wq); } static void mdp5_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus) @@ -1234,6 +1234,7 @@ static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc) struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state); struct mdp5_ctl *ctl = mdp5_cstate->ctl; + wait_queue_head_t *queue = drm_crtc_vblank_waitqueue(crtc); int ret; /* Should not call this function if crtc is disabled. */ @@ -1244,7 +1245,7 @@ static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc) if (ret) return; - ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue, + ret = wait_event_timeout(*queue, ((mdp5_ctl_get_commit_status(ctl) & mdp5_crtc->flushed_mask) == 0), msecs_to_jiffies(50)); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c index 666de99a46a5..fc183fe37f56 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c @@ -3,6 +3,7 @@ * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. */ +#include <linux/string_choices.h> #include "mdp5_kms.h" #include "mdp5_ctl.h" @@ -233,7 +234,7 @@ int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl, return -EINVAL; ctl->encoder_enabled = enabled; - DBG("intf_%d: %s", intf->num, enabled ? "on" : "off"); + DBG("intf_%d: %s", intf->num, str_on_off(enabled)); if (start_signal_needed(ctl, pipeline)) { send_start_signal(ctl); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 374704cce656..61edf6864092 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -198,11 +198,12 @@ static void mdp5_destroy(struct mdp5_kms *mdp5_kms); static void mdp5_kms_destroy(struct msm_kms *kms) { struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); - struct msm_gem_address_space *aspace = kms->aspace; - if (aspace) { - aspace->mmu->funcs->detach(aspace->mmu); - msm_gem_address_space_put(aspace); + if (kms->vm) { + struct msm_mmu *mmu = to_msm_vm(kms->vm)->mmu; + + mmu->funcs->detach(mmu); + drm_gpuvm_put(kms->vm); } mdp_kms_destroy(&mdp5_kms->base); @@ -311,7 +312,7 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, DRM_DEV_INFO(dev->dev, "Skipping eDP interface %d\n", intf->num); break; case INTF_HDMI: - if (!priv->hdmi) + if (!priv->kms->hdmi) break; ctl = mdp5_ctlm_request(ctlm, intf->num); @@ -326,7 +327,7 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, break; } - ret = msm_hdmi_modeset_init(priv->hdmi, dev, encoder); + ret = msm_hdmi_modeset_init(priv->kms->hdmi, dev, encoder); break; case INTF_DSI: { @@ -334,14 +335,14 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, mdp5_cfg_get_hw_config(mdp5_kms->cfg); int dsi_id = get_dsi_id_from_intf(hw_cfg, intf->num); - if ((dsi_id >= ARRAY_SIZE(priv->dsi)) || (dsi_id < 0)) { + if ((dsi_id >= ARRAY_SIZE(priv->kms->dsi)) || (dsi_id < 0)) { DRM_DEV_ERROR(dev->dev, "failed to find dsi from intf %d\n", intf->num); ret = -EINVAL; break; } - if (!priv->dsi[dsi_id]) + if (!priv->kms->dsi[dsi_id]) break; ctl = mdp5_ctlm_request(ctlm, intf->num); @@ -356,9 +357,10 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, break; } - ret = msm_dsi_modeset_init(priv->dsi[dsi_id], dev, encoder); + ret = msm_dsi_modeset_init(priv->kms->dsi[dsi_id], dev, encoder); if (!ret) - mdp5_encoder_set_intf_mode(encoder, msm_dsi_is_cmd_mode(priv->dsi[dsi_id])); + mdp5_encoder_set_intf_mode(encoder, + msm_dsi_is_cmd_mode(priv->kms->dsi[dsi_id])); break; } @@ -374,7 +376,6 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, static int modeset_init(struct mdp5_kms *mdp5_kms) { struct drm_device *dev = mdp5_kms->dev; - struct msm_drm_private *priv = dev->dev_private; unsigned int num_crtcs; int i, ret, pi = 0, ci = 0; struct drm_plane *primary[MAX_BASES] = { NULL }; @@ -442,7 +443,6 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) DRM_DEV_ERROR(dev->dev, "failed to construct crtc %d (%d)\n", i, ret); goto fail; } - priv->num_crtcs++; } /* @@ -450,7 +450,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) * crtcs for the encoders */ drm_for_each_encoder(encoder, dev) - encoder->possible_crtcs = (1 << priv->num_crtcs) - 1; + encoder->possible_crtcs = (1 << dev->mode_config.num_crtc) - 1; return 0; @@ -500,7 +500,7 @@ static int mdp5_kms_init(struct drm_device *dev) struct mdp5_kms *mdp5_kms; struct mdp5_cfg *config; struct msm_kms *kms = priv->kms; - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; int i, ret; ret = mdp5_init(to_platform_device(dev->dev), dev); @@ -534,13 +534,13 @@ static int mdp5_kms_init(struct drm_device *dev) } mdelay(16); - aspace = msm_kms_init_aspace(mdp5_kms->dev); - if (IS_ERR(aspace)) { - ret = PTR_ERR(aspace); + vm = msm_kms_init_vm(mdp5_kms->dev, pdev->dev.parent); + if (IS_ERR(vm)) { + ret = PTR_ERR(vm); goto fail; } - kms->aspace = aspace; + kms->vm = vm; pm_runtime_put_sync(&pdev->dev); @@ -908,7 +908,7 @@ MODULE_DEVICE_TABLE(of, mdp5_dt_match); static struct platform_driver mdp5_driver = { .probe = mdp5_dev_probe, - .remove_new = mdp5_dev_remove, + .remove = mdp5_dev_remove, .shutdown = msm_kms_shutdown, .driver = { .name = "msm_mdp", diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c index 62de248ed1b0..4ca183fb61a9 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c @@ -135,8 +135,6 @@ static const struct drm_plane_funcs mdp5_plane_funcs = { static int mdp5_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { - struct msm_drm_private *priv = plane->dev->dev_private; - struct msm_kms *kms = priv->kms; bool needs_dirtyfb = to_mdp5_plane_state(new_state)->needs_dirtyfb; if (!new_state->fb) @@ -144,14 +142,12 @@ static int mdp5_plane_prepare_fb(struct drm_plane *plane, drm_gem_plane_helper_prepare_fb(plane, new_state); - return msm_framebuffer_prepare(new_state->fb, kms->aspace, needs_dirtyfb); + return msm_framebuffer_prepare(new_state->fb, needs_dirtyfb); } static void mdp5_plane_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state) { - struct mdp5_kms *mdp5_kms = get_kms(plane); - struct msm_kms *kms = &mdp5_kms->base.base; struct drm_framebuffer *fb = old_state->fb; bool needed_dirtyfb = to_mdp5_plane_state(old_state)->needs_dirtyfb; @@ -159,7 +155,7 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane, return; DBG("%s: cleanup: FB[%u]", plane->name, fb->base.id); - msm_framebuffer_cleanup(fb, kms->aspace, needed_dirtyfb); + msm_framebuffer_cleanup(fb, needed_dirtyfb); } static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state, @@ -340,8 +336,7 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane, if (!crtc) return 0; - crtc_state = drm_atomic_get_existing_crtc_state(state, - crtc); + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); if (WARN_ON(!crtc_state)) return -EINVAL; @@ -368,7 +363,7 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane, } static int mdp5_plane_atomic_async_check(struct drm_plane *plane, - struct drm_atomic_state *state) + struct drm_atomic_state *state, bool flip) { struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); @@ -377,8 +372,8 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane, int min_scale, max_scale; int ret; - crtc_state = drm_atomic_get_existing_crtc_state(state, - new_plane_state->crtc); + crtc_state = drm_atomic_get_new_crtc_state(state, + new_plane_state->crtc); if (WARN_ON(!crtc_state)) return -EINVAL; @@ -467,8 +462,6 @@ static void set_scanout_locked(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe, struct drm_framebuffer *fb) { - struct msm_kms *kms = &mdp5_kms->base.base; - mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_STRIDE_A(pipe), MDP5_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) | MDP5_PIPE_SRC_STRIDE_A_P1(fb->pitches[1])); @@ -478,13 +471,13 @@ static void set_scanout_locked(struct mdp5_kms *mdp5_kms, MDP5_PIPE_SRC_STRIDE_B_P3(fb->pitches[3])); mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC0_ADDR(pipe), - msm_framebuffer_iova(fb, kms->aspace, 0)); + msm_framebuffer_iova(fb, 0)); mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC1_ADDR(pipe), - msm_framebuffer_iova(fb, kms->aspace, 1)); + msm_framebuffer_iova(fb, 1)); mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC2_ADDR(pipe), - msm_framebuffer_iova(fb, kms->aspace, 2)); + msm_framebuffer_iova(fb, 2)); mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC3_ADDR(pipe), - msm_framebuffer_iova(fb, kms->aspace, 3)); + msm_framebuffer_iova(fb, 3)); } /* Note: mdp5_plane->pipe_lock must be locked */ diff --git a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c index e75b97127c0d..2be00b11e557 100644 --- a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c +++ b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c @@ -109,7 +109,7 @@ int msm_disp_snapshot_init(struct drm_device *drm_dev) mutex_init(&kms->dump_mutex); - kms->dump_worker = kthread_create_worker(0, "%s", "disp_snapshot"); + kms->dump_worker = kthread_run_worker(0, "%s", "disp_snapshot"); if (IS_ERR(kms->dump_worker)) DRM_ERROR("failed to create disp state task\n"); diff --git a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.h b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.h index b5f452bd7ada..53bd1dcde15f 100644 --- a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.h +++ b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.h @@ -38,6 +38,7 @@ * struct msm_disp_state - structure to store current dpu state * @dev: device pointer * @drm_dev: drm device pointer + * @blocks: list head for hardware state blocks * @atomic_state: atomic state duplicated at the time of the error * @time: timestamp at which the coredump was captured */ @@ -55,7 +56,7 @@ struct msm_disp_state { /** * struct msm_disp_state_block - structure to store each hardware block state * @name: name of the block - * @drm_dev: handle to the linked list head + * @node: handle to the linked list head * @size: size of the register space of this hardware block * @state: array holding the register dump of this hardware block * @base_addr: starting address of this hardware block's register space @@ -88,8 +89,9 @@ void msm_disp_snapshot_destroy(struct drm_device *drm_dev); * msm_disp_snapshot_state_sync - synchronously snapshot display state * @kms: the kms object * - * Returns state or error + * Returns: state or error * + * Context: * Must be called with &kms->dump_mutex held */ struct msm_disp_state *msm_disp_snapshot_state_sync(struct msm_kms *kms); @@ -97,7 +99,7 @@ struct msm_disp_state *msm_disp_snapshot_state_sync(struct msm_kms *kms); /** * msm_disp_snapshot_state - trigger to dump the display snapshot * @drm_dev: handle to drm device - + * * Returns: none */ void msm_disp_snapshot_state(struct drm_device *drm_dev); @@ -114,7 +116,7 @@ void msm_disp_state_print(struct msm_disp_state *disp_state, struct drm_printer /** * msm_disp_snapshot_capture_state - utility to capture atomic state and hw registers * @disp_state: handle to msm_disp_state struct - + * * Returns: none */ void msm_disp_snapshot_capture_state(struct msm_disp_state *disp_state); @@ -122,7 +124,7 @@ void msm_disp_snapshot_capture_state(struct msm_disp_state *disp_state); /** * msm_disp_state_free - free the memory after the coredump has been read * @data: handle to struct msm_disp_state - + * * Returns: none */ void msm_disp_state_free(void *data); @@ -130,7 +132,6 @@ void msm_disp_state_free(void *data); /** * msm_disp_snapshot_add_block - add a hardware block with its register dump * @disp_state: handle to struct msm_disp_state - * @name: name of the hardware block * @len: size of the register space of the hardware block * @base_addr: starting address of the register space of the hardware block * @fmt: format in which the block names need to be printed diff --git a/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c b/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c index 07a2c1e87219..19b470968f4d 100644 --- a/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c +++ b/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c @@ -82,8 +82,7 @@ void msm_disp_state_print(struct msm_disp_state *state, struct drm_printer *p) drm_printf(p, "kernel: " UTS_RELEASE "\n"); drm_printf(p, "module: " KBUILD_MODNAME "\n"); drm_printf(p, "dpu devcoredump\n"); - drm_printf(p, "time: %lld.%09ld\n", - state->time.tv_sec, state->time.tv_nsec); + drm_printf(p, "time: %ptSp\n", &state->time); list_for_each_entry_safe(block, tmp, &state->blocks, node) { drm_printf(p, "====================%s================\n", block->name); @@ -127,18 +126,18 @@ void msm_disp_snapshot_capture_state(struct msm_disp_state *disp_state) priv = drm_dev->dev_private; kms = priv->kms; - for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { - if (!priv->dp[i]) + for (i = 0; i < ARRAY_SIZE(kms->dp); i++) { + if (!kms->dp[i]) continue; - msm_dp_snapshot(disp_state, priv->dp[i]); + msm_dp_snapshot(disp_state, kms->dp[i]); } - for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) { - if (!priv->dsi[i]) + for (i = 0; i < ARRAY_SIZE(kms->dsi); i++) { + if (!kms->dsi[i]) continue; - msm_dsi_snapshot(disp_state, priv->dsi[i]); + msm_dsi_snapshot(disp_state, kms->dsi[i]); } if (kms->funcs->snapshot) diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 74e01a5dd419..41018e82efa1 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -11,273 +11,157 @@ #include <drm/display/drm_dp_helper.h> #include <drm/drm_edid.h> -#include "dp_catalog.h" #include "dp_audio.h" +#include "dp_drm.h" #include "dp_panel.h" +#include "dp_reg.h" #include "dp_display.h" #include "dp_utils.h" struct msm_dp_audio_private { - struct platform_device *audio_pdev; struct platform_device *pdev; struct drm_device *drm_dev; - struct msm_dp_catalog *catalog; + void __iomem *link_base; u32 channels; struct msm_dp_audio msm_dp_audio; }; -static u32 msm_dp_audio_get_header(struct msm_dp_catalog *catalog, - enum msm_dp_catalog_audio_sdp_type sdp, - enum msm_dp_catalog_audio_header_type header) +static inline u32 msm_dp_read_link(struct msm_dp_audio_private *audio, u32 offset) { - return msm_dp_catalog_audio_get_header(catalog, sdp, header); + return readl_relaxed(audio->link_base + offset); } -static void msm_dp_audio_set_header(struct msm_dp_catalog *catalog, - u32 data, - enum msm_dp_catalog_audio_sdp_type sdp, - enum msm_dp_catalog_audio_header_type header) +static inline void msm_dp_write_link(struct msm_dp_audio_private *audio, + u32 offset, u32 data) { - msm_dp_catalog_audio_set_header(catalog, sdp, header, data); + /* + * To make sure link reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + writel(data, audio->link_base + offset); } static void msm_dp_audio_stream_sdp(struct msm_dp_audio_private *audio) { - struct msm_dp_catalog *catalog = audio->catalog; - u32 value, new_value; - u8 parity_byte; - - /* Config header and parity byte 1 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1); - - new_value = 0x02; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_1_BIT) - | (parity_byte << PARITY_BYTE_1_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1); - - /* Config header and parity byte 2 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2); - new_value = value; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_2_BIT) - | (parity_byte << PARITY_BYTE_2_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2); - - /* Config header and parity byte 3 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3); - - new_value = audio->channels - 1; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_3_BIT) - | (parity_byte << PARITY_BYTE_3_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3); + struct dp_sdp_header sdp_hdr = { + .HB0 = 0x00, + .HB1 = 0x02, + .HB2 = 0x00, + .HB3 = audio->channels - 1, + }; + u32 header[2]; + + msm_dp_utils_pack_sdp_header(&sdp_hdr, header); + + msm_dp_write_link(audio, MMSS_DP_AUDIO_STREAM_0, header[0]); + msm_dp_write_link(audio, MMSS_DP_AUDIO_STREAM_1, header[1]); } static void msm_dp_audio_timestamp_sdp(struct msm_dp_audio_private *audio) { - struct msm_dp_catalog *catalog = audio->catalog; - u32 value, new_value; - u8 parity_byte; - - /* Config header and parity byte 1 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1); - - new_value = 0x1; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_1_BIT) - | (parity_byte << PARITY_BYTE_1_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1); - - /* Config header and parity byte 2 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2); - - new_value = 0x17; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_2_BIT) - | (parity_byte << PARITY_BYTE_2_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2); - - /* Config header and parity byte 3 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3); - - new_value = (0x0 | (0x11 << 2)); - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_3_BIT) - | (parity_byte << PARITY_BYTE_3_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3); + struct dp_sdp_header sdp_hdr = { + .HB0 = 0x00, + .HB1 = 0x01, + .HB2 = 0x17, + .HB3 = 0x0 | (0x11 << 2), + }; + u32 header[2]; + + msm_dp_utils_pack_sdp_header(&sdp_hdr, header); + + msm_dp_write_link(audio, MMSS_DP_AUDIO_TIMESTAMP_0, header[0]); + msm_dp_write_link(audio, MMSS_DP_AUDIO_TIMESTAMP_1, header[1]); } static void msm_dp_audio_infoframe_sdp(struct msm_dp_audio_private *audio) { - struct msm_dp_catalog *catalog = audio->catalog; - u32 value, new_value; - u8 parity_byte; - - /* Config header and parity byte 1 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1); - - new_value = 0x84; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_1_BIT) - | (parity_byte << PARITY_BYTE_1_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1); - - /* Config header and parity byte 2 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2); - - new_value = 0x1b; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_2_BIT) - | (parity_byte << PARITY_BYTE_2_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2); - - /* Config header and parity byte 3 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3); - - new_value = (0x0 | (0x11 << 2)); - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_3_BIT) - | (parity_byte << PARITY_BYTE_3_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", - new_value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3); + struct dp_sdp_header sdp_hdr = { + .HB0 = 0x00, + .HB1 = 0x84, + .HB2 = 0x1b, + .HB3 = 0x0 | (0x11 << 2), + }; + u32 header[2]; + + msm_dp_utils_pack_sdp_header(&sdp_hdr, header); + + msm_dp_write_link(audio, MMSS_DP_AUDIO_INFOFRAME_0, header[0]); + msm_dp_write_link(audio, MMSS_DP_AUDIO_INFOFRAME_1, header[1]); } static void msm_dp_audio_copy_management_sdp(struct msm_dp_audio_private *audio) { - struct msm_dp_catalog *catalog = audio->catalog; - u32 value, new_value; - u8 parity_byte; - - /* Config header and parity byte 1 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1); - - new_value = 0x05; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_1_BIT) - | (parity_byte << PARITY_BYTE_1_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1); - - /* Config header and parity byte 2 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2); - - new_value = 0x0F; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_2_BIT) - | (parity_byte << PARITY_BYTE_2_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2); - - /* Config header and parity byte 3 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3); - - new_value = 0x0; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_3_BIT) - | (parity_byte << PARITY_BYTE_3_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3); + struct dp_sdp_header sdp_hdr = { + .HB0 = 0x00, + .HB1 = 0x05, + .HB2 = 0x0f, + .HB3 = 0x00, + }; + u32 header[2]; + + msm_dp_utils_pack_sdp_header(&sdp_hdr, header); + + msm_dp_write_link(audio, MMSS_DP_AUDIO_COPYMANAGEMENT_0, header[0]); + msm_dp_write_link(audio, MMSS_DP_AUDIO_COPYMANAGEMENT_1, header[1]); } static void msm_dp_audio_isrc_sdp(struct msm_dp_audio_private *audio) { - struct msm_dp_catalog *catalog = audio->catalog; - u32 value, new_value; - u8 parity_byte; - - /* Config header and parity byte 1 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1); - - new_value = 0x06; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_1_BIT) - | (parity_byte << PARITY_BYTE_1_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1); - - /* Config header and parity byte 2 */ - value = msm_dp_audio_get_header(catalog, - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2); - - new_value = 0x0F; - parity_byte = msm_dp_utils_calculate_parity(new_value); - value |= ((new_value << HEADER_BYTE_2_BIT) - | (parity_byte << PARITY_BYTE_2_BIT)); - drm_dbg_dp(audio->drm_dev, - "Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - msm_dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2); + struct dp_sdp_header sdp_hdr = { + .HB0 = 0x00, + .HB1 = 0x06, + .HB2 = 0x0f, + .HB3 = 0x00, + }; + u32 header[2]; + u32 reg; + + /* XXX: is it necessary to preserve this field? */ + reg = msm_dp_read_link(audio, MMSS_DP_AUDIO_ISRC_1); + sdp_hdr.HB3 = FIELD_GET(HEADER_3_MASK, reg); + + msm_dp_utils_pack_sdp_header(&sdp_hdr, header); + + msm_dp_write_link(audio, MMSS_DP_AUDIO_ISRC_0, header[0]); + msm_dp_write_link(audio, MMSS_DP_AUDIO_ISRC_1, header[1]); +} + +static void msm_dp_audio_config_sdp(struct msm_dp_audio_private *audio) +{ + u32 sdp_cfg, sdp_cfg2; + + sdp_cfg = msm_dp_read_link(audio, MMSS_DP_SDP_CFG); + /* AUDIO_TIMESTAMP_SDP_EN */ + sdp_cfg |= BIT(1); + /* AUDIO_STREAM_SDP_EN */ + sdp_cfg |= BIT(2); + /* AUDIO_COPY_MANAGEMENT_SDP_EN */ + sdp_cfg |= BIT(5); + /* AUDIO_ISRC_SDP_EN */ + sdp_cfg |= BIT(6); + /* AUDIO_INFOFRAME_SDP_EN */ + sdp_cfg |= BIT(20); + + drm_dbg_dp(audio->drm_dev, "sdp_cfg = 0x%x\n", sdp_cfg); + + msm_dp_write_link(audio, MMSS_DP_SDP_CFG, sdp_cfg); + + sdp_cfg2 = msm_dp_read_link(audio, MMSS_DP_SDP_CFG2); + /* IFRM_REGSRC -> Do not use reg values */ + sdp_cfg2 &= ~BIT(0); + /* AUDIO_STREAM_HB3_REGSRC-> Do not use reg values */ + sdp_cfg2 &= ~BIT(1); + + drm_dbg_dp(audio->drm_dev, "sdp_cfg2 = 0x%x\n", sdp_cfg2); + + msm_dp_write_link(audio, MMSS_DP_SDP_CFG2, sdp_cfg2); } static void msm_dp_audio_setup_sdp(struct msm_dp_audio_private *audio) { - msm_dp_catalog_audio_config_sdp(audio->catalog); + msm_dp_audio_config_sdp(audio); msm_dp_audio_stream_sdp(audio); msm_dp_audio_timestamp_sdp(audio); @@ -288,8 +172,7 @@ static void msm_dp_audio_setup_sdp(struct msm_dp_audio_private *audio) static void msm_dp_audio_setup_acr(struct msm_dp_audio_private *audio) { - u32 select = 0; - struct msm_dp_catalog *catalog = audio->catalog; + u32 select, acr_ctrl; switch (audio->msm_dp_audio.bw_code) { case DP_LINK_BW_1_62: @@ -310,13 +193,17 @@ static void msm_dp_audio_setup_acr(struct msm_dp_audio_private *audio) break; } - msm_dp_catalog_audio_config_acr(catalog, select); + acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14); + + drm_dbg_dp(audio->drm_dev, "select: %#x, acr_ctrl: %#x\n", + select, acr_ctrl); + + msm_dp_write_link(audio, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl); } static void msm_dp_audio_safe_to_exit_level(struct msm_dp_audio_private *audio) { - struct msm_dp_catalog *catalog = audio->catalog; - u32 safe_to_exit_level = 0; + u32 safe_to_exit_level, mainlink_levels; switch (audio->msm_dp_audio.lane_count) { case 1: @@ -329,41 +216,47 @@ static void msm_dp_audio_safe_to_exit_level(struct msm_dp_audio_private *audio) safe_to_exit_level = 5; break; default: + safe_to_exit_level = 14; drm_dbg_dp(audio->drm_dev, "setting the default safe_to_exit_level = %u\n", safe_to_exit_level); - safe_to_exit_level = 14; break; } - msm_dp_catalog_audio_sfe_level(catalog, safe_to_exit_level); + mainlink_levels = msm_dp_read_link(audio, REG_DP_MAINLINK_LEVELS); + mainlink_levels &= 0xFE0; + mainlink_levels |= safe_to_exit_level; + + drm_dbg_dp(audio->drm_dev, + "mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n", + mainlink_levels, safe_to_exit_level); + + msm_dp_write_link(audio, REG_DP_MAINLINK_LEVELS, mainlink_levels); } static void msm_dp_audio_enable(struct msm_dp_audio_private *audio, bool enable) { - struct msm_dp_catalog *catalog = audio->catalog; + u32 audio_ctrl; - msm_dp_catalog_audio_enable(catalog, enable); + audio_ctrl = msm_dp_read_link(audio, MMSS_DP_AUDIO_CFG); + + if (enable) + audio_ctrl |= BIT(0); + else + audio_ctrl &= ~BIT(0); + + drm_dbg_dp(audio->drm_dev, "dp_audio_cfg = 0x%x\n", audio_ctrl); + + msm_dp_write_link(audio, MMSS_DP_AUDIO_CFG, audio_ctrl); + /* make sure audio engine is disabled */ + wmb(); } -static struct msm_dp_audio_private *msm_dp_audio_get_data(struct platform_device *pdev) +static struct msm_dp_audio_private *msm_dp_audio_get_data(struct msm_dp *msm_dp_display) { struct msm_dp_audio *msm_dp_audio; - struct msm_dp *msm_dp_display; - - if (!pdev) { - DRM_ERROR("invalid input\n"); - return ERR_PTR(-ENODEV); - } - - msm_dp_display = platform_get_drvdata(pdev); - if (!msm_dp_display) { - DRM_ERROR("invalid input\n"); - return ERR_PTR(-ENODEV); - } msm_dp_audio = msm_dp_display->msm_dp_audio; - if (!msm_dp_audio) { DRM_ERROR("invalid msm_dp_audio data\n"); return ERR_PTR(-EINVAL); @@ -372,66 +265,16 @@ static struct msm_dp_audio_private *msm_dp_audio_get_data(struct platform_device return container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio); } -static int msm_dp_audio_hook_plugged_cb(struct device *dev, void *data, - hdmi_codec_plugged_cb fn, - struct device *codec_dev) -{ - - struct platform_device *pdev; - struct msm_dp *msm_dp_display; - - pdev = to_platform_device(dev); - if (!pdev) { - pr_err("invalid input\n"); - return -ENODEV; - } - - msm_dp_display = platform_get_drvdata(pdev); - if (!msm_dp_display) { - pr_err("invalid input\n"); - return -ENODEV; - } - - return msm_dp_display_set_plugged_cb(msm_dp_display, fn, codec_dev); -} - -static int msm_dp_audio_get_eld(struct device *dev, - void *data, uint8_t *buf, size_t len) -{ - struct platform_device *pdev; - struct msm_dp *msm_dp_display; - - pdev = to_platform_device(dev); - - if (!pdev) { - DRM_ERROR("invalid input\n"); - return -ENODEV; - } - - msm_dp_display = platform_get_drvdata(pdev); - if (!msm_dp_display) { - DRM_ERROR("invalid input\n"); - return -ENODEV; - } - - memcpy(buf, msm_dp_display->connector->eld, - min(sizeof(msm_dp_display->connector->eld), len)); - - return 0; -} - -int msm_dp_audio_hw_params(struct device *dev, - void *data, - struct hdmi_codec_daifmt *daifmt, - struct hdmi_codec_params *params) +int msm_dp_audio_prepare(struct drm_bridge *bridge, + struct drm_connector *connector, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params) { int rc = 0; struct msm_dp_audio_private *audio; - struct platform_device *pdev; struct msm_dp *msm_dp_display; - pdev = to_platform_device(dev); - msm_dp_display = platform_get_drvdata(pdev); + msm_dp_display = to_dp_bridge(bridge)->msm_dp_display; /* * there could be cases where sound card can be opened even @@ -446,7 +289,7 @@ int msm_dp_audio_hw_params(struct device *dev, goto end; } - audio = msm_dp_audio_get_data(pdev); + audio = msm_dp_audio_get_data(msm_dp_display); if (IS_ERR(audio)) { rc = PTR_ERR(audio); goto end; @@ -465,15 +308,14 @@ end: return rc; } -static void msm_dp_audio_shutdown(struct device *dev, void *data) +void msm_dp_audio_shutdown(struct drm_bridge *bridge, + struct drm_connector *connecter) { struct msm_dp_audio_private *audio; - struct platform_device *pdev; struct msm_dp *msm_dp_display; - pdev = to_platform_device(dev); - msm_dp_display = platform_get_drvdata(pdev); - audio = msm_dp_audio_get_data(pdev); + msm_dp_display = to_dp_bridge(bridge)->msm_dp_display; + audio = msm_dp_audio_get_data(msm_dp_display); if (IS_ERR(audio)) { DRM_ERROR("failed to get audio data\n"); return; @@ -495,56 +337,14 @@ static void msm_dp_audio_shutdown(struct device *dev, void *data) msm_dp_display_signal_audio_complete(msm_dp_display); } -static const struct hdmi_codec_ops msm_dp_audio_codec_ops = { - .hw_params = msm_dp_audio_hw_params, - .audio_shutdown = msm_dp_audio_shutdown, - .get_eld = msm_dp_audio_get_eld, - .hook_plugged_cb = msm_dp_audio_hook_plugged_cb, -}; - -static struct hdmi_codec_pdata codec_data = { - .ops = &msm_dp_audio_codec_ops, - .max_i2s_channels = 8, - .i2s = 1, -}; - -void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm_dp_audio) -{ - struct msm_dp_audio_private *audio_priv; - - audio_priv = container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio); - - if (audio_priv->audio_pdev) { - platform_device_unregister(audio_priv->audio_pdev); - audio_priv->audio_pdev = NULL; - } -} - -int msm_dp_register_audio_driver(struct device *dev, - struct msm_dp_audio *msm_dp_audio) -{ - struct msm_dp_audio_private *audio_priv; - - audio_priv = container_of(msm_dp_audio, - struct msm_dp_audio_private, msm_dp_audio); - - audio_priv->audio_pdev = platform_device_register_data(dev, - HDMI_CODEC_DRV_NAME, - PLATFORM_DEVID_AUTO, - &codec_data, - sizeof(codec_data)); - return PTR_ERR_OR_ZERO(audio_priv->audio_pdev); -} - struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev, - struct msm_dp_panel *panel, - struct msm_dp_catalog *catalog) + void __iomem *link_base) { int rc = 0; struct msm_dp_audio_private *audio; struct msm_dp_audio *msm_dp_audio; - if (!pdev || !panel || !catalog) { + if (!pdev) { DRM_ERROR("invalid input\n"); rc = -EINVAL; goto error; @@ -557,12 +357,10 @@ struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev, } audio->pdev = pdev; - audio->catalog = catalog; + audio->link_base = link_base; msm_dp_audio = &audio->msm_dp_audio; - msm_dp_catalog_audio_init(catalog); - return msm_dp_audio; error: return ERR_PTR(rc); diff --git a/drivers/gpu/drm/msm/dp/dp_audio.h b/drivers/gpu/drm/msm/dp/dp_audio.h index 1c9efaaa40e5..ce2342856adb 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.h +++ b/drivers/gpu/drm/msm/dp/dp_audio.h @@ -8,10 +8,10 @@ #include <linux/platform_device.h> -#include "dp_panel.h" -#include "dp_catalog.h" #include <sound/hdmi-codec.h> +struct drm_bridge; + /** * struct msm_dp_audio * @lane_count: number of lanes configured in current session @@ -28,32 +28,13 @@ struct msm_dp_audio { * Creates and instance of dp audio. * * @pdev: caller's platform device instance. - * @panel: an instance of msm_dp_panel module. - * @catalog: an instance of msm_dp_catalog module. + * @link_base: pointer to the msm_dp_link resource. * * Returns the error code in case of failure, otherwize * an instance of newly created msm_dp_module. */ struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev, - struct msm_dp_panel *panel, - struct msm_dp_catalog *catalog); - -/** - * msm_dp_register_audio_driver() - * - * Registers DP device with hdmi_codec interface. - * - * @dev: DP device instance. - * @msm_dp_audio: an instance of msm_dp_audio module. - * - * - * Returns the error code in case of failure, otherwise - * zero on success. - */ -int msm_dp_register_audio_driver(struct device *dev, - struct msm_dp_audio *msm_dp_audio); - -void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm_dp_audio); + void __iomem *link_base); /** * msm_dp_audio_put() @@ -64,10 +45,12 @@ void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm */ void msm_dp_audio_put(struct msm_dp_audio *msm_dp_audio); -int msm_dp_audio_hw_params(struct device *dev, - void *data, - struct hdmi_codec_daifmt *daifmt, - struct hdmi_codec_params *params); +int msm_dp_audio_prepare(struct drm_bridge *bridge, + struct drm_connector *connector, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params); +void msm_dp_audio_shutdown(struct drm_bridge *bridge, + struct drm_connector *connector); #endif /* _DP_AUDIO_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index bc8d46abfc61..3825a2fb48e2 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -4,6 +4,7 @@ */ #include <linux/delay.h> +#include <linux/iopoll.h> #include <linux/phy/phy.h> #include <drm/drm_print.h> @@ -22,7 +23,7 @@ enum msm_dp_aux_err { struct msm_dp_aux_private { struct device *dev; - struct msm_dp_catalog *catalog; + void __iomem *aux_base; struct phy *phy; @@ -45,6 +46,80 @@ struct msm_dp_aux_private { struct drm_dp_aux msm_dp_aux; }; +static inline u32 msm_dp_read_aux(struct msm_dp_aux_private *aux, u32 offset) +{ + return readl_relaxed(aux->aux_base + offset); +} + +static inline void msm_dp_write_aux(struct msm_dp_aux_private *aux, + u32 offset, u32 data) +{ + /* + * To make sure aux reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + writel(data, aux->aux_base + offset); +} + +static void msm_dp_aux_clear_hw_interrupts(struct msm_dp_aux_private *aux) +{ + msm_dp_read_aux(aux, REG_DP_PHY_AUX_INTERRUPT_STATUS); + msm_dp_write_aux(aux, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x1f); + msm_dp_write_aux(aux, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x9f); + msm_dp_write_aux(aux, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0); +} + +/* + * NOTE: resetting AUX controller will also clear any pending HPD related interrupts + */ +static void msm_dp_aux_reset(struct msm_dp_aux_private *aux) +{ + u32 aux_ctrl; + + aux_ctrl = msm_dp_read_aux(aux, REG_DP_AUX_CTRL); + + aux_ctrl |= DP_AUX_CTRL_RESET; + msm_dp_write_aux(aux, REG_DP_AUX_CTRL, aux_ctrl); + usleep_range(1000, 1100); /* h/w recommended delay */ + + aux_ctrl &= ~DP_AUX_CTRL_RESET; + msm_dp_write_aux(aux, REG_DP_AUX_CTRL, aux_ctrl); +} + +static void msm_dp_aux_enable(struct msm_dp_aux_private *aux) +{ + u32 aux_ctrl; + + aux_ctrl = msm_dp_read_aux(aux, REG_DP_AUX_CTRL); + + msm_dp_write_aux(aux, REG_DP_TIMEOUT_COUNT, 0xffff); + msm_dp_write_aux(aux, REG_DP_AUX_LIMITS, 0xffff); + + aux_ctrl |= DP_AUX_CTRL_ENABLE; + msm_dp_write_aux(aux, REG_DP_AUX_CTRL, aux_ctrl); +} + +static void msm_dp_aux_disable(struct msm_dp_aux_private *aux) +{ + u32 aux_ctrl; + + aux_ctrl = msm_dp_read_aux(aux, REG_DP_AUX_CTRL); + aux_ctrl &= ~DP_AUX_CTRL_ENABLE; + msm_dp_write_aux(aux, REG_DP_AUX_CTRL, aux_ctrl); +} + +static int msm_dp_aux_wait_for_hpd_connect_state(struct msm_dp_aux_private *aux, + unsigned long wait_us) +{ + u32 state; + + /* poll for hpd connected status every 2ms and timeout after wait_us */ + return readl_poll_timeout(aux->aux_base + + REG_DP_DP_HPD_INT_STATUS, + state, state & DP_DP_HPD_STATE_STATUS_CONNECTED, + min(wait_us, 2000), wait_us); +} + #define MAX_AUX_RETRIES 5 static ssize_t msm_dp_aux_write(struct msm_dp_aux_private *aux, @@ -88,11 +163,11 @@ static ssize_t msm_dp_aux_write(struct msm_dp_aux_private *aux, /* index = 0, write */ if (i == 0) reg |= DP_AUX_DATA_INDEX_WRITE; - msm_dp_catalog_aux_write_data(aux->catalog, reg); + msm_dp_write_aux(aux, REG_DP_AUX_DATA, reg); } - msm_dp_catalog_aux_clear_trans(aux->catalog, false); - msm_dp_catalog_aux_clear_hw_interrupts(aux->catalog); + msm_dp_write_aux(aux, REG_DP_AUX_TRANS_CTRL, 0); + msm_dp_aux_clear_hw_interrupts(aux); reg = 0; /* Transaction number == 1 */ if (!aux->native) { /* i2c */ @@ -106,7 +181,7 @@ static ssize_t msm_dp_aux_write(struct msm_dp_aux_private *aux, } reg |= DP_AUX_TRANS_CTRL_GO; - msm_dp_catalog_aux_write_trans(aux->catalog, reg); + msm_dp_write_aux(aux, REG_DP_AUX_TRANS_CTRL, reg); return len; } @@ -139,20 +214,22 @@ static ssize_t msm_dp_aux_cmd_fifo_rx(struct msm_dp_aux_private *aux, u32 i, actual_i; u32 len = msg->size; - msm_dp_catalog_aux_clear_trans(aux->catalog, true); + data = msm_dp_read_aux(aux, REG_DP_AUX_TRANS_CTRL); + data &= ~DP_AUX_TRANS_CTRL_GO; + msm_dp_write_aux(aux, REG_DP_AUX_TRANS_CTRL, data); data = DP_AUX_DATA_INDEX_WRITE; /* INDEX_WRITE */ data |= DP_AUX_DATA_READ; /* read */ - msm_dp_catalog_aux_write_data(aux->catalog, data); + msm_dp_write_aux(aux, REG_DP_AUX_DATA, data); dp = msg->buffer; /* discard first byte */ - data = msm_dp_catalog_aux_read_data(aux->catalog); + data = msm_dp_read_aux(aux, REG_DP_AUX_DATA); for (i = 0; i < len; i++) { - data = msm_dp_catalog_aux_read_data(aux->catalog); + data = msm_dp_read_aux(aux, REG_DP_AUX_DATA); *dp++ = (u8)((data >> DP_AUX_DATA_OFFSET) & 0xff); actual_i = (data >> DP_AUX_DATA_INDEX_OFFSET) & 0xFF; @@ -335,8 +412,8 @@ static ssize_t msm_dp_aux_transfer(struct drm_dp_aux *msm_dp_aux, phy_calibrate(aux->phy); } /* reset aux if link is in connected state */ - if (msm_dp_catalog_link_is_connected(aux->catalog)) - msm_dp_catalog_aux_reset(aux->catalog); + if (msm_dp_aux_is_link_connected(msm_dp_aux)) + msm_dp_aux_reset(aux); } else { aux->retry_cnt = 0; switch (aux->aux_error_num) { @@ -369,9 +446,8 @@ exit: return ret; } -irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux) +irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux, u32 isr) { - u32 isr; struct msm_dp_aux_private *aux; if (!msm_dp_aux) { @@ -381,12 +457,6 @@ irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux) aux = container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux); - isr = msm_dp_catalog_aux_get_irq(aux->catalog); - - /* no interrupts pending, return immediately */ - if (!isr) - return IRQ_NONE; - if (!aux->cmd_busy) { DRM_ERROR("Unexpected DP AUX IRQ %#010x when not busy\n", isr); return IRQ_NONE; @@ -403,7 +473,7 @@ irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux) if (isr & DP_INTR_AUX_ERROR) { aux->aux_error_num = DP_AUX_ERR_PHY; - msm_dp_catalog_aux_clear_hw_interrupts(aux->catalog); + msm_dp_aux_clear_hw_interrupts(aux); } else if (isr & DP_INTR_NACK_DEFER) { aux->aux_error_num = DP_AUX_ERR_NACK_DEFER; } else if (isr & DP_INTR_WRONG_ADDR) { @@ -444,7 +514,7 @@ void msm_dp_aux_reconfig(struct drm_dp_aux *msm_dp_aux) aux = container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux); phy_calibrate(aux->phy); - msm_dp_catalog_aux_reset(aux->catalog); + msm_dp_aux_reset(aux); } void msm_dp_aux_init(struct drm_dp_aux *msm_dp_aux) @@ -460,7 +530,7 @@ void msm_dp_aux_init(struct drm_dp_aux *msm_dp_aux) mutex_lock(&aux->mutex); - msm_dp_catalog_aux_enable(aux->catalog, true); + msm_dp_aux_enable(aux); aux->retry_cnt = 0; aux->initted = true; @@ -476,7 +546,7 @@ void msm_dp_aux_deinit(struct drm_dp_aux *msm_dp_aux) mutex_lock(&aux->mutex); aux->initted = false; - msm_dp_catalog_aux_enable(aux->catalog, false); + msm_dp_aux_disable(aux); mutex_unlock(&aux->mutex); } @@ -517,23 +587,105 @@ static int msm_dp_wait_hpd_asserted(struct drm_dp_aux *msm_dp_aux, if (ret) return ret; - ret = msm_dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog, wait_us); + ret = msm_dp_aux_wait_for_hpd_connect_state(aux, wait_us); pm_runtime_put_sync(aux->dev); return ret; } -struct drm_dp_aux *msm_dp_aux_get(struct device *dev, struct msm_dp_catalog *catalog, +void msm_dp_aux_hpd_enable(struct drm_dp_aux *msm_dp_aux) +{ + struct msm_dp_aux_private *aux = + container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux); + u32 reg; + + /* Configure REFTIMER and enable it */ + reg = msm_dp_read_aux(aux, REG_DP_DP_HPD_REFTIMER); + reg |= DP_DP_HPD_REFTIMER_ENABLE; + msm_dp_write_aux(aux, REG_DP_DP_HPD_REFTIMER, reg); + + /* Enable HPD */ + msm_dp_write_aux(aux, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN); +} + +void msm_dp_aux_hpd_disable(struct drm_dp_aux *msm_dp_aux) +{ + struct msm_dp_aux_private *aux = + container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux); + u32 reg; + + reg = msm_dp_read_aux(aux, REG_DP_DP_HPD_REFTIMER); + reg &= ~DP_DP_HPD_REFTIMER_ENABLE; + msm_dp_write_aux(aux, REG_DP_DP_HPD_REFTIMER, reg); + + msm_dp_write_aux(aux, REG_DP_DP_HPD_CTRL, 0); +} + +void msm_dp_aux_hpd_intr_enable(struct drm_dp_aux *msm_dp_aux) +{ + struct msm_dp_aux_private *aux = + container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux); + u32 reg; + + reg = msm_dp_read_aux(aux, REG_DP_DP_HPD_INT_MASK); + reg |= DP_DP_HPD_INT_MASK; + msm_dp_write_aux(aux, REG_DP_DP_HPD_INT_MASK, + reg & DP_DP_HPD_INT_MASK); +} + +void msm_dp_aux_hpd_intr_disable(struct drm_dp_aux *msm_dp_aux) +{ + struct msm_dp_aux_private *aux = + container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux); + u32 reg; + + reg = msm_dp_read_aux(aux, REG_DP_DP_HPD_INT_MASK); + reg &= ~DP_DP_HPD_INT_MASK; + msm_dp_write_aux(aux, REG_DP_DP_HPD_INT_MASK, + reg & DP_DP_HPD_INT_MASK); +} + +u32 msm_dp_aux_get_hpd_intr_status(struct drm_dp_aux *msm_dp_aux) +{ + struct msm_dp_aux_private *aux = + container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux); + int isr, mask; + + isr = msm_dp_read_aux(aux, REG_DP_DP_HPD_INT_STATUS); + msm_dp_write_aux(aux, REG_DP_DP_HPD_INT_ACK, + (isr & DP_DP_HPD_INT_MASK)); + mask = msm_dp_read_aux(aux, REG_DP_DP_HPD_INT_MASK); + + /* + * We only want to return interrupts that are unmasked to the caller. + * However, the interrupt status field also contains other + * informational bits about the HPD state status, so we only mask + * out the part of the register that tells us about which interrupts + * are pending. + */ + return isr & (mask | ~DP_DP_HPD_INT_MASK); +} + +u32 msm_dp_aux_is_link_connected(struct drm_dp_aux *msm_dp_aux) +{ + struct msm_dp_aux_private *aux = + container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux); + u32 status; + + status = msm_dp_read_aux(aux, REG_DP_DP_HPD_INT_STATUS); + status >>= DP_DP_HPD_STATE_STATUS_BITS_SHIFT; + status &= DP_DP_HPD_STATE_STATUS_BITS_MASK; + + return status; +} + +struct drm_dp_aux *msm_dp_aux_get(struct device *dev, struct phy *phy, - bool is_edp) + bool is_edp, + void __iomem *aux_base) { struct msm_dp_aux_private *aux; - if (!catalog) { - DRM_ERROR("invalid input\n"); - return ERR_PTR(-ENODEV); - } - aux = devm_kzalloc(dev, sizeof(*aux), GFP_KERNEL); if (!aux) return ERR_PTR(-ENOMEM); @@ -544,9 +696,9 @@ struct drm_dp_aux *msm_dp_aux_get(struct device *dev, struct msm_dp_catalog *cat mutex_init(&aux->mutex); aux->dev = dev; - aux->catalog = catalog; aux->phy = phy; aux->retry_cnt = 0; + aux->aux_base = aux_base; /* * Use the drm_dp_aux_init() to use the aux adapter diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h index 39c5b4c8596a..4be02e8b4d0b 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.h +++ b/drivers/gpu/drm/msm/dp/dp_aux.h @@ -6,21 +6,28 @@ #ifndef _DP_AUX_H_ #define _DP_AUX_H_ -#include "dp_catalog.h" #include <drm/display/drm_dp_helper.h> int msm_dp_aux_register(struct drm_dp_aux *msm_dp_aux); void msm_dp_aux_unregister(struct drm_dp_aux *msm_dp_aux); -irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux); +irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux, u32 isr); void msm_dp_aux_enable_xfers(struct drm_dp_aux *msm_dp_aux, bool enabled); void msm_dp_aux_init(struct drm_dp_aux *msm_dp_aux); void msm_dp_aux_deinit(struct drm_dp_aux *msm_dp_aux); void msm_dp_aux_reconfig(struct drm_dp_aux *msm_dp_aux); +void msm_dp_aux_hpd_enable(struct drm_dp_aux *msm_dp_aux); +void msm_dp_aux_hpd_disable(struct drm_dp_aux *msm_dp_aux); +void msm_dp_aux_hpd_intr_enable(struct drm_dp_aux *msm_dp_aux); +void msm_dp_aux_hpd_intr_disable(struct drm_dp_aux *msm_dp_aux); +u32 msm_dp_aux_get_hpd_intr_status(struct drm_dp_aux *msm_dp_aux); +u32 msm_dp_aux_is_link_connected(struct drm_dp_aux *msm_dp_aux); + struct phy; -struct drm_dp_aux *msm_dp_aux_get(struct device *dev, struct msm_dp_catalog *catalog, +struct drm_dp_aux *msm_dp_aux_get(struct device *dev, struct phy *phy, - bool is_edp); + bool is_edp, + void __iomem *aux_base); void msm_dp_aux_put(struct drm_dp_aux *aux); #endif /*__DP_AUX_H_*/ diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c deleted file mode 100644 index b4c8856fb25d..000000000000 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ /dev/null @@ -1,1341 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include <linux/delay.h> -#include <linux/iopoll.h> -#include <linux/platform_device.h> -#include <linux/rational.h> -#include <drm/display/drm_dp_helper.h> -#include <drm/drm_print.h> - -#include "dp_catalog.h" -#include "dp_reg.h" - -#define POLLING_SLEEP_US 1000 -#define POLLING_TIMEOUT_US 10000 - -#define SCRAMBLER_RESET_COUNT_VALUE 0xFC - -#define DP_INTERRUPT_STATUS_ACK_SHIFT 1 -#define DP_INTERRUPT_STATUS_MASK_SHIFT 2 - -#define DP_INTF_CONFIG_DATABUS_WIDEN BIT(4) - -#define DP_INTERRUPT_STATUS1 \ - (DP_INTR_AUX_XFER_DONE| \ - DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \ - DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \ - DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \ - DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR) - -#define DP_INTERRUPT_STATUS1_ACK \ - (DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_ACK_SHIFT) -#define DP_INTERRUPT_STATUS1_MASK \ - (DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_MASK_SHIFT) - -#define DP_INTERRUPT_STATUS2 \ - (DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \ - DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED) - -#define DP_INTERRUPT_STATUS2_ACK \ - (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_ACK_SHIFT) -#define DP_INTERRUPT_STATUS2_MASK \ - (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT) - -#define DP_INTERRUPT_STATUS4 \ - (PSR_UPDATE_INT | PSR_CAPTURE_INT | PSR_EXIT_INT | \ - PSR_UPDATE_ERROR_INT | PSR_WAKE_ERROR_INT) - -#define DP_INTERRUPT_MASK4 \ - (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \ - PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK) - -#define DP_DEFAULT_AHB_OFFSET 0x0000 -#define DP_DEFAULT_AHB_SIZE 0x0200 -#define DP_DEFAULT_AUX_OFFSET 0x0200 -#define DP_DEFAULT_AUX_SIZE 0x0200 -#define DP_DEFAULT_LINK_OFFSET 0x0400 -#define DP_DEFAULT_LINK_SIZE 0x0C00 -#define DP_DEFAULT_P0_OFFSET 0x1000 -#define DP_DEFAULT_P0_SIZE 0x0400 - -struct dss_io_region { - size_t len; - void __iomem *base; -}; - -struct dss_io_data { - struct dss_io_region ahb; - struct dss_io_region aux; - struct dss_io_region link; - struct dss_io_region p0; -}; - -struct msm_dp_catalog_private { - struct device *dev; - struct drm_device *drm_dev; - struct dss_io_data io; - u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX]; - struct msm_dp_catalog msm_dp_catalog; -}; - -void msm_dp_catalog_snapshot(struct msm_dp_catalog *msm_dp_catalog, struct msm_disp_state *disp_state) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - struct dss_io_data *dss = &catalog->io; - - msm_disp_snapshot_add_block(disp_state, dss->ahb.len, dss->ahb.base, "dp_ahb"); - msm_disp_snapshot_add_block(disp_state, dss->aux.len, dss->aux.base, "dp_aux"); - msm_disp_snapshot_add_block(disp_state, dss->link.len, dss->link.base, "dp_link"); - msm_disp_snapshot_add_block(disp_state, dss->p0.len, dss->p0.base, "dp_p0"); -} - -static inline u32 msm_dp_read_aux(struct msm_dp_catalog_private *catalog, u32 offset) -{ - return readl_relaxed(catalog->io.aux.base + offset); -} - -static inline void msm_dp_write_aux(struct msm_dp_catalog_private *catalog, - u32 offset, u32 data) -{ - /* - * To make sure aux reg writes happens before any other operation, - * this function uses writel() instread of writel_relaxed() - */ - writel(data, catalog->io.aux.base + offset); -} - -static inline u32 msm_dp_read_ahb(const struct msm_dp_catalog_private *catalog, u32 offset) -{ - return readl_relaxed(catalog->io.ahb.base + offset); -} - -static inline void msm_dp_write_ahb(struct msm_dp_catalog_private *catalog, - u32 offset, u32 data) -{ - /* - * To make sure phy reg writes happens before any other operation, - * this function uses writel() instread of writel_relaxed() - */ - writel(data, catalog->io.ahb.base + offset); -} - -static inline void msm_dp_write_p0(struct msm_dp_catalog_private *catalog, - u32 offset, u32 data) -{ - /* - * To make sure interface reg writes happens before any other operation, - * this function uses writel() instread of writel_relaxed() - */ - writel(data, catalog->io.p0.base + offset); -} - -static inline u32 msm_dp_read_p0(struct msm_dp_catalog_private *catalog, - u32 offset) -{ - /* - * To make sure interface reg writes happens before any other operation, - * this function uses writel() instread of writel_relaxed() - */ - return readl_relaxed(catalog->io.p0.base + offset); -} - -static inline u32 msm_dp_read_link(struct msm_dp_catalog_private *catalog, u32 offset) -{ - return readl_relaxed(catalog->io.link.base + offset); -} - -static inline void msm_dp_write_link(struct msm_dp_catalog_private *catalog, - u32 offset, u32 data) -{ - /* - * To make sure link reg writes happens before any other operation, - * this function uses writel() instread of writel_relaxed() - */ - writel(data, catalog->io.link.base + offset); -} - -/* aux related catalog functions */ -u32 msm_dp_catalog_aux_read_data(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - return msm_dp_read_aux(catalog, REG_DP_AUX_DATA); -} - -int msm_dp_catalog_aux_write_data(struct msm_dp_catalog *msm_dp_catalog, u32 data) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - msm_dp_write_aux(catalog, REG_DP_AUX_DATA, data); - return 0; -} - -int msm_dp_catalog_aux_write_trans(struct msm_dp_catalog *msm_dp_catalog, u32 data) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - msm_dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, data); - return 0; -} - -int msm_dp_catalog_aux_clear_trans(struct msm_dp_catalog *msm_dp_catalog, bool read) -{ - u32 data; - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - if (read) { - data = msm_dp_read_aux(catalog, REG_DP_AUX_TRANS_CTRL); - data &= ~DP_AUX_TRANS_CTRL_GO; - msm_dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, data); - } else { - msm_dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, 0); - } - return 0; -} - -int msm_dp_catalog_aux_clear_hw_interrupts(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - msm_dp_read_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_STATUS); - msm_dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x1f); - msm_dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x9f); - msm_dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0); - return 0; -} - -/** - * msm_dp_catalog_aux_reset() - reset AUX controller - * - * @msm_dp_catalog: DP catalog structure - * - * return: void - * - * This function reset AUX controller - * - * NOTE: reset AUX controller will also clear any pending HPD related interrupts - * - */ -void msm_dp_catalog_aux_reset(struct msm_dp_catalog *msm_dp_catalog) -{ - u32 aux_ctrl; - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - aux_ctrl = msm_dp_read_aux(catalog, REG_DP_AUX_CTRL); - - aux_ctrl |= DP_AUX_CTRL_RESET; - msm_dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); - usleep_range(1000, 1100); /* h/w recommended delay */ - - aux_ctrl &= ~DP_AUX_CTRL_RESET; - msm_dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); -} - -void msm_dp_catalog_aux_enable(struct msm_dp_catalog *msm_dp_catalog, bool enable) -{ - u32 aux_ctrl; - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - aux_ctrl = msm_dp_read_aux(catalog, REG_DP_AUX_CTRL); - - if (enable) { - msm_dp_write_aux(catalog, REG_DP_TIMEOUT_COUNT, 0xffff); - msm_dp_write_aux(catalog, REG_DP_AUX_LIMITS, 0xffff); - aux_ctrl |= DP_AUX_CTRL_ENABLE; - } else { - aux_ctrl &= ~DP_AUX_CTRL_ENABLE; - } - - msm_dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); -} - -int msm_dp_catalog_aux_wait_for_hpd_connect_state(struct msm_dp_catalog *msm_dp_catalog, - unsigned long wait_us) -{ - u32 state; - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - /* poll for hpd connected status every 2ms and timeout after wait_us */ - return readl_poll_timeout(catalog->io.aux.base + - REG_DP_DP_HPD_INT_STATUS, - state, state & DP_DP_HPD_STATE_STATUS_CONNECTED, - min(wait_us, 2000), wait_us); -} - -static void dump_regs(void __iomem *base, int len) -{ - int i; - u32 x0, x4, x8, xc; - u32 addr_off = 0; - - len = DIV_ROUND_UP(len, 16); - for (i = 0; i < len; i++) { - x0 = readl_relaxed(base + addr_off); - x4 = readl_relaxed(base + addr_off + 0x04); - x8 = readl_relaxed(base + addr_off + 0x08); - xc = readl_relaxed(base + addr_off + 0x0c); - - pr_info("%08x: %08x %08x %08x %08x", addr_off, x0, x4, x8, xc); - addr_off += 16; - } -} - -void msm_dp_catalog_dump_regs(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - struct dss_io_data *io = &catalog->io; - - pr_info("AHB regs\n"); - dump_regs(io->ahb.base, io->ahb.len); - - pr_info("AUXCLK regs\n"); - dump_regs(io->aux.base, io->aux.len); - - pr_info("LCLK regs\n"); - dump_regs(io->link.base, io->link.len); - - pr_info("P0CLK regs\n"); - dump_regs(io->p0.base, io->p0.len); -} - -u32 msm_dp_catalog_aux_get_irq(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - u32 intr, intr_ack; - - intr = msm_dp_read_ahb(catalog, REG_DP_INTR_STATUS); - intr &= ~DP_INTERRUPT_STATUS1_MASK; - intr_ack = (intr & DP_INTERRUPT_STATUS1) - << DP_INTERRUPT_STATUS_ACK_SHIFT; - msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS, intr_ack | - DP_INTERRUPT_STATUS1_MASK); - - return intr; - -} - -/* controller related catalog functions */ -void msm_dp_catalog_ctrl_update_transfer_unit(struct msm_dp_catalog *msm_dp_catalog, - u32 msm_dp_tu, u32 valid_boundary, - u32 valid_boundary2) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - msm_dp_write_link(catalog, REG_DP_VALID_BOUNDARY, valid_boundary); - msm_dp_write_link(catalog, REG_DP_TU, msm_dp_tu); - msm_dp_write_link(catalog, REG_DP_VALID_BOUNDARY_2, valid_boundary2); -} - -void msm_dp_catalog_ctrl_state_ctrl(struct msm_dp_catalog *msm_dp_catalog, u32 state) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - msm_dp_write_link(catalog, REG_DP_STATE_CTRL, state); -} - -void msm_dp_catalog_ctrl_config_ctrl(struct msm_dp_catalog *msm_dp_catalog, u32 cfg) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - drm_dbg_dp(catalog->drm_dev, "DP_CONFIGURATION_CTRL=0x%x\n", cfg); - - msm_dp_write_link(catalog, REG_DP_CONFIGURATION_CTRL, cfg); -} - -void msm_dp_catalog_ctrl_lane_mapping(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - u32 ln_0 = 0, ln_1 = 1, ln_2 = 2, ln_3 = 3; /* One-to-One mapping */ - u32 ln_mapping; - - ln_mapping = ln_0 << LANE0_MAPPING_SHIFT; - ln_mapping |= ln_1 << LANE1_MAPPING_SHIFT; - ln_mapping |= ln_2 << LANE2_MAPPING_SHIFT; - ln_mapping |= ln_3 << LANE3_MAPPING_SHIFT; - - msm_dp_write_link(catalog, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING, - ln_mapping); -} - -void msm_dp_catalog_ctrl_psr_mainlink_enable(struct msm_dp_catalog *msm_dp_catalog, - bool enable) -{ - u32 val; - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - val = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL); - - if (enable) - val |= DP_MAINLINK_CTRL_ENABLE; - else - val &= ~DP_MAINLINK_CTRL_ENABLE; - - msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, val); -} - -void msm_dp_catalog_ctrl_mainlink_ctrl(struct msm_dp_catalog *msm_dp_catalog, - bool enable) -{ - u32 mainlink_ctrl; - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - drm_dbg_dp(catalog->drm_dev, "enable=%d\n", enable); - if (enable) { - /* - * To make sure link reg writes happens before other operation, - * msm_dp_write_link() function uses writel() - */ - mainlink_ctrl = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL); - - mainlink_ctrl &= ~(DP_MAINLINK_CTRL_RESET | - DP_MAINLINK_CTRL_ENABLE); - msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); - - mainlink_ctrl |= DP_MAINLINK_CTRL_RESET; - msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); - - mainlink_ctrl &= ~DP_MAINLINK_CTRL_RESET; - msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); - - mainlink_ctrl |= (DP_MAINLINK_CTRL_ENABLE | - DP_MAINLINK_FB_BOUNDARY_SEL); - msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); - } else { - mainlink_ctrl = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL); - mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE; - msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); - } -} - -void msm_dp_catalog_ctrl_config_misc(struct msm_dp_catalog *msm_dp_catalog, - u32 colorimetry_cfg, - u32 test_bits_depth) -{ - u32 misc_val; - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - misc_val = msm_dp_read_link(catalog, REG_DP_MISC1_MISC0); - - /* clear bpp bits */ - misc_val &= ~(0x07 << DP_MISC0_TEST_BITS_DEPTH_SHIFT); - misc_val |= colorimetry_cfg << DP_MISC0_COLORIMETRY_CFG_SHIFT; - misc_val |= test_bits_depth << DP_MISC0_TEST_BITS_DEPTH_SHIFT; - /* Configure clock to synchronous mode */ - misc_val |= DP_MISC0_SYNCHRONOUS_CLK; - - drm_dbg_dp(catalog->drm_dev, "misc settings = 0x%x\n", misc_val); - msm_dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val); -} - -void msm_dp_catalog_setup_peripheral_flush(struct msm_dp_catalog *msm_dp_catalog) -{ - u32 mainlink_ctrl, hw_revision; - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - mainlink_ctrl = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL); - - hw_revision = msm_dp_catalog_hw_revision(msm_dp_catalog); - if (hw_revision >= DP_HW_VERSION_1_2) - mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE; - else - mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_UPDATE_SDP; - - msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); -} - -void msm_dp_catalog_ctrl_config_msa(struct msm_dp_catalog *msm_dp_catalog, - u32 rate, u32 stream_rate_khz, - bool is_ycbcr_420) -{ - u32 pixel_m, pixel_n; - u32 mvid, nvid, pixel_div = 0, dispcc_input_rate; - u32 const nvid_fixed = DP_LINK_CONSTANT_N_VALUE; - u32 const link_rate_hbr2 = 540000; - u32 const link_rate_hbr3 = 810000; - unsigned long den, num; - - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - if (rate == link_rate_hbr3) - pixel_div = 6; - else if (rate == 162000 || rate == 270000) - pixel_div = 2; - else if (rate == link_rate_hbr2) - pixel_div = 4; - else - DRM_ERROR("Invalid pixel mux divider\n"); - - dispcc_input_rate = (rate * 10) / pixel_div; - - rational_best_approximation(dispcc_input_rate, stream_rate_khz, - (unsigned long)(1 << 16) - 1, - (unsigned long)(1 << 16) - 1, &den, &num); - - den = ~(den - num); - den = den & 0xFFFF; - pixel_m = num; - pixel_n = den; - - mvid = (pixel_m & 0xFFFF) * 5; - nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); - - if (nvid < nvid_fixed) { - u32 temp; - - temp = (nvid_fixed / nvid) * nvid; - mvid = (nvid_fixed / nvid) * mvid; - nvid = temp; - } - - if (is_ycbcr_420) - mvid /= 2; - - if (link_rate_hbr2 == rate) - nvid *= 2; - - if (link_rate_hbr3 == rate) - nvid *= 3; - - drm_dbg_dp(catalog->drm_dev, "mvid=0x%x, nvid=0x%x\n", mvid, nvid); - msm_dp_write_link(catalog, REG_DP_SOFTWARE_MVID, mvid); - msm_dp_write_link(catalog, REG_DP_SOFTWARE_NVID, nvid); - msm_dp_write_p0(catalog, MMSS_DP_DSC_DTO, 0x0); -} - -int msm_dp_catalog_ctrl_set_pattern_state_bit(struct msm_dp_catalog *msm_dp_catalog, - u32 state_bit) -{ - int bit, ret; - u32 data; - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - bit = BIT(state_bit - 1); - drm_dbg_dp(catalog->drm_dev, "hw: bit=%d train=%d\n", bit, state_bit); - msm_dp_catalog_ctrl_state_ctrl(msm_dp_catalog, bit); - - bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT; - - /* Poll for mainlink ready status */ - ret = readx_poll_timeout(readl, catalog->io.link.base + - REG_DP_MAINLINK_READY, - data, data & bit, - POLLING_SLEEP_US, POLLING_TIMEOUT_US); - if (ret < 0) { - DRM_ERROR("set state_bit for link_train=%d failed\n", state_bit); - return ret; - } - return 0; -} - -/** - * msm_dp_catalog_hw_revision() - retrieve DP hw revision - * - * @msm_dp_catalog: DP catalog structure - * - * Return: DP controller hw revision - * - */ -u32 msm_dp_catalog_hw_revision(const struct msm_dp_catalog *msm_dp_catalog) -{ - const struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - return msm_dp_read_ahb(catalog, REG_DP_HW_VERSION); -} - -/** - * msm_dp_catalog_ctrl_reset() - reset DP controller - * - * @msm_dp_catalog: DP catalog structure - * - * return: void - * - * This function reset the DP controller - * - * NOTE: reset DP controller will also clear any pending HPD related interrupts - * - */ -void msm_dp_catalog_ctrl_reset(struct msm_dp_catalog *msm_dp_catalog) -{ - u32 sw_reset; - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - sw_reset = msm_dp_read_ahb(catalog, REG_DP_SW_RESET); - - sw_reset |= DP_SW_RESET; - msm_dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset); - usleep_range(1000, 1100); /* h/w recommended delay */ - - sw_reset &= ~DP_SW_RESET; - msm_dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset); -} - -bool msm_dp_catalog_ctrl_mainlink_ready(struct msm_dp_catalog *msm_dp_catalog) -{ - u32 data; - int ret; - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - /* Poll for mainlink ready status */ - ret = readl_poll_timeout(catalog->io.link.base + - REG_DP_MAINLINK_READY, - data, data & DP_MAINLINK_READY_FOR_VIDEO, - POLLING_SLEEP_US, POLLING_TIMEOUT_US); - if (ret < 0) { - DRM_ERROR("mainlink not ready\n"); - return false; - } - - return true; -} - -void msm_dp_catalog_ctrl_enable_irq(struct msm_dp_catalog *msm_dp_catalog, - bool enable) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - if (enable) { - msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS, - DP_INTERRUPT_STATUS1_MASK); - msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS2, - DP_INTERRUPT_STATUS2_MASK); - } else { - msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS, 0x00); - msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 0x00); - } -} - -void msm_dp_catalog_hpd_config_intr(struct msm_dp_catalog *msm_dp_catalog, - u32 intr_mask, bool en) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - u32 config = msm_dp_read_aux(catalog, REG_DP_DP_HPD_INT_MASK); - - config = (en ? config | intr_mask : config & ~intr_mask); - - drm_dbg_dp(catalog->drm_dev, "intr_mask=%#x config=%#x\n", - intr_mask, config); - msm_dp_write_aux(catalog, REG_DP_DP_HPD_INT_MASK, - config & DP_DP_HPD_INT_MASK); -} - -void msm_dp_catalog_ctrl_hpd_enable(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - u32 reftimer = msm_dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER); - - /* Configure REFTIMER and enable it */ - reftimer |= DP_DP_HPD_REFTIMER_ENABLE; - msm_dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer); - - /* Enable HPD */ - msm_dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN); -} - -void msm_dp_catalog_ctrl_hpd_disable(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - u32 reftimer = msm_dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER); - - reftimer &= ~DP_DP_HPD_REFTIMER_ENABLE; - msm_dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer); - - msm_dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, 0); -} - -static void msm_dp_catalog_enable_sdp(struct msm_dp_catalog_private *catalog) -{ - /* trigger sdp */ - msm_dp_write_link(catalog, MMSS_DP_SDP_CFG3, UPDATE_SDP); - msm_dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x0); -} - -void msm_dp_catalog_ctrl_config_psr(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - u32 config; - - /* enable PSR1 function */ - config = msm_dp_read_link(catalog, REG_PSR_CONFIG); - config |= PSR1_SUPPORTED; - msm_dp_write_link(catalog, REG_PSR_CONFIG, config); - - msm_dp_write_ahb(catalog, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4); - msm_dp_catalog_enable_sdp(catalog); -} - -void msm_dp_catalog_ctrl_set_psr(struct msm_dp_catalog *msm_dp_catalog, bool enter) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - u32 cmd; - - cmd = msm_dp_read_link(catalog, REG_PSR_CMD); - - cmd &= ~(PSR_ENTER | PSR_EXIT); - - if (enter) - cmd |= PSR_ENTER; - else - cmd |= PSR_EXIT; - - msm_dp_catalog_enable_sdp(catalog); - msm_dp_write_link(catalog, REG_PSR_CMD, cmd); -} - -u32 msm_dp_catalog_link_is_connected(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - u32 status; - - status = msm_dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS); - drm_dbg_dp(catalog->drm_dev, "aux status: %#x\n", status); - status >>= DP_DP_HPD_STATE_STATUS_BITS_SHIFT; - status &= DP_DP_HPD_STATE_STATUS_BITS_MASK; - - return status; -} - -u32 msm_dp_catalog_hpd_get_intr_status(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - int isr, mask; - - isr = msm_dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS); - msm_dp_write_aux(catalog, REG_DP_DP_HPD_INT_ACK, - (isr & DP_DP_HPD_INT_MASK)); - mask = msm_dp_read_aux(catalog, REG_DP_DP_HPD_INT_MASK); - - /* - * We only want to return interrupts that are unmasked to the caller. - * However, the interrupt status field also contains other - * informational bits about the HPD state status, so we only mask - * out the part of the register that tells us about which interrupts - * are pending. - */ - return isr & (mask | ~DP_DP_HPD_INT_MASK); -} - -u32 msm_dp_catalog_ctrl_read_psr_interrupt_status(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - u32 intr, intr_ack; - - intr = msm_dp_read_ahb(catalog, REG_DP_INTR_STATUS4); - intr_ack = (intr & DP_INTERRUPT_STATUS4) - << DP_INTERRUPT_STATUS_ACK_SHIFT; - msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS4, intr_ack); - - return intr; -} - -int msm_dp_catalog_ctrl_get_interrupt(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - u32 intr, intr_ack; - - intr = msm_dp_read_ahb(catalog, REG_DP_INTR_STATUS2); - intr &= ~DP_INTERRUPT_STATUS2_MASK; - intr_ack = (intr & DP_INTERRUPT_STATUS2) - << DP_INTERRUPT_STATUS_ACK_SHIFT; - msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS2, - intr_ack | DP_INTERRUPT_STATUS2_MASK); - - return intr; -} - -void msm_dp_catalog_ctrl_phy_reset(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - msm_dp_write_ahb(catalog, REG_DP_PHY_CTRL, - DP_PHY_CTRL_SW_RESET | DP_PHY_CTRL_SW_RESET_PLL); - usleep_range(1000, 1100); /* h/w recommended delay */ - msm_dp_write_ahb(catalog, REG_DP_PHY_CTRL, 0x0); -} - -void msm_dp_catalog_ctrl_send_phy_pattern(struct msm_dp_catalog *msm_dp_catalog, - u32 pattern) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - u32 value = 0x0; - - /* Make sure to clear the current pattern before starting a new one */ - msm_dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0); - - drm_dbg_dp(catalog->drm_dev, "pattern: %#x\n", pattern); - switch (pattern) { - case DP_PHY_TEST_PATTERN_D10_2: - msm_dp_write_link(catalog, REG_DP_STATE_CTRL, - DP_STATE_CTRL_LINK_TRAINING_PATTERN1); - break; - case DP_PHY_TEST_PATTERN_ERROR_COUNT: - value &= ~(1 << 16); - msm_dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, - value); - value |= SCRAMBLER_RESET_COUNT_VALUE; - msm_dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, - value); - msm_dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, - DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); - msm_dp_write_link(catalog, REG_DP_STATE_CTRL, - DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); - break; - case DP_PHY_TEST_PATTERN_PRBS7: - msm_dp_write_link(catalog, REG_DP_STATE_CTRL, - DP_STATE_CTRL_LINK_PRBS7); - break; - case DP_PHY_TEST_PATTERN_80BIT_CUSTOM: - msm_dp_write_link(catalog, REG_DP_STATE_CTRL, - DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN); - /* 00111110000011111000001111100000 */ - msm_dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0, - 0x3E0F83E0); - /* 00001111100000111110000011111000 */ - msm_dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1, - 0x0F83E0F8); - /* 1111100000111110 */ - msm_dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2, - 0x0000F83E); - break; - case DP_PHY_TEST_PATTERN_CP2520: - value = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL); - value &= ~DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER; - msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value); - - value = DP_HBR2_ERM_PATTERN; - msm_dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, - value); - value |= SCRAMBLER_RESET_COUNT_VALUE; - msm_dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, - value); - msm_dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, - DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); - msm_dp_write_link(catalog, REG_DP_STATE_CTRL, - DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); - value = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL); - value |= DP_MAINLINK_CTRL_ENABLE; - msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value); - break; - case DP_PHY_TEST_PATTERN_SEL_MASK: - msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, - DP_MAINLINK_CTRL_ENABLE); - msm_dp_write_link(catalog, REG_DP_STATE_CTRL, - DP_STATE_CTRL_LINK_TRAINING_PATTERN4); - break; - default: - drm_dbg_dp(catalog->drm_dev, - "No valid test pattern requested: %#x\n", pattern); - break; - } -} - -u32 msm_dp_catalog_ctrl_read_phy_pattern(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - return msm_dp_read_link(catalog, REG_DP_MAINLINK_READY); -} - -/* panel related catalog functions */ -int msm_dp_catalog_panel_timing_cfg(struct msm_dp_catalog *msm_dp_catalog, u32 total, - u32 sync_start, u32 width_blanking, u32 msm_dp_active) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - u32 reg; - - msm_dp_write_link(catalog, REG_DP_TOTAL_HOR_VER, total); - msm_dp_write_link(catalog, REG_DP_START_HOR_VER_FROM_SYNC, sync_start); - msm_dp_write_link(catalog, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, width_blanking); - msm_dp_write_link(catalog, REG_DP_ACTIVE_HOR_VER, msm_dp_active); - - reg = msm_dp_read_p0(catalog, MMSS_DP_INTF_CONFIG); - - if (msm_dp_catalog->wide_bus_en) - reg |= DP_INTF_CONFIG_DATABUS_WIDEN; - else - reg &= ~DP_INTF_CONFIG_DATABUS_WIDEN; - - - DRM_DEBUG_DP("wide_bus_en=%d reg=%#x\n", msm_dp_catalog->wide_bus_en, reg); - - msm_dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, reg); - return 0; -} - -static void msm_dp_catalog_panel_send_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog, struct dp_sdp *vsc_sdp) -{ - struct msm_dp_catalog_private *catalog; - u32 header[2]; - u32 val; - int i; - - catalog = container_of(msm_dp_catalog, struct msm_dp_catalog_private, msm_dp_catalog); - - msm_dp_utils_pack_sdp_header(&vsc_sdp->sdp_header, header); - - msm_dp_write_link(catalog, MMSS_DP_GENERIC0_0, header[0]); - msm_dp_write_link(catalog, MMSS_DP_GENERIC0_1, header[1]); - - for (i = 0; i < sizeof(vsc_sdp->db); i += 4) { - val = ((vsc_sdp->db[i]) | (vsc_sdp->db[i + 1] << 8) | (vsc_sdp->db[i + 2] << 16) | - (vsc_sdp->db[i + 3] << 24)); - msm_dp_write_link(catalog, MMSS_DP_GENERIC0_2 + i, val); - } -} - -static void msm_dp_catalog_panel_update_sdp(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog; - u32 hw_revision; - - catalog = container_of(msm_dp_catalog, struct msm_dp_catalog_private, msm_dp_catalog); - - hw_revision = msm_dp_catalog_hw_revision(msm_dp_catalog); - if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= DP_HW_VERSION_1_0) { - msm_dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01); - msm_dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00); - } -} - -void msm_dp_catalog_panel_enable_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog, struct dp_sdp *vsc_sdp) -{ - struct msm_dp_catalog_private *catalog; - u32 cfg, cfg2, misc; - - catalog = container_of(msm_dp_catalog, struct msm_dp_catalog_private, msm_dp_catalog); - - cfg = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG); - cfg2 = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG2); - misc = msm_dp_read_link(catalog, REG_DP_MISC1_MISC0); - - cfg |= GEN0_SDP_EN; - msm_dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg); - - cfg2 |= GENERIC0_SDPSIZE_VALID; - msm_dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2); - - msm_dp_catalog_panel_send_vsc_sdp(msm_dp_catalog, vsc_sdp); - - /* indicates presence of VSC (BIT(6) of MISC1) */ - misc |= DP_MISC1_VSC_SDP; - - drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=1\n"); - - pr_debug("misc settings = 0x%x\n", misc); - msm_dp_write_link(catalog, REG_DP_MISC1_MISC0, misc); - - msm_dp_catalog_panel_update_sdp(msm_dp_catalog); -} - -void msm_dp_catalog_panel_disable_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog; - u32 cfg, cfg2, misc; - - catalog = container_of(msm_dp_catalog, struct msm_dp_catalog_private, msm_dp_catalog); - - cfg = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG); - cfg2 = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG2); - misc = msm_dp_read_link(catalog, REG_DP_MISC1_MISC0); - - cfg &= ~GEN0_SDP_EN; - msm_dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg); - - cfg2 &= ~GENERIC0_SDPSIZE_VALID; - msm_dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2); - - /* switch back to MSA */ - misc &= ~DP_MISC1_VSC_SDP; - - drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=0\n"); - - pr_debug("misc settings = 0x%x\n", misc); - msm_dp_write_link(catalog, REG_DP_MISC1_MISC0, misc); - - msm_dp_catalog_panel_update_sdp(msm_dp_catalog); -} - -void msm_dp_catalog_panel_tpg_enable(struct msm_dp_catalog *msm_dp_catalog, - struct drm_display_mode *drm_mode) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - u32 hsync_period, vsync_period; - u32 display_v_start, display_v_end; - u32 hsync_start_x, hsync_end_x; - u32 v_sync_width; - u32 hsync_ctl; - u32 display_hctl; - - /* TPG config parameters*/ - hsync_period = drm_mode->htotal; - vsync_period = drm_mode->vtotal; - - display_v_start = ((drm_mode->vtotal - drm_mode->vsync_start) * - hsync_period); - display_v_end = ((vsync_period - (drm_mode->vsync_start - - drm_mode->vdisplay)) - * hsync_period) - 1; - - display_v_start += drm_mode->htotal - drm_mode->hsync_start; - display_v_end -= (drm_mode->hsync_start - drm_mode->hdisplay); - - hsync_start_x = drm_mode->htotal - drm_mode->hsync_start; - hsync_end_x = hsync_period - (drm_mode->hsync_start - - drm_mode->hdisplay) - 1; - - v_sync_width = drm_mode->vsync_end - drm_mode->vsync_start; - - hsync_ctl = (hsync_period << 16) | - (drm_mode->hsync_end - drm_mode->hsync_start); - display_hctl = (hsync_end_x << 16) | hsync_start_x; - - - msm_dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0x0); - msm_dp_write_p0(catalog, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl); - msm_dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period * - hsync_period); - msm_dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width * - hsync_period); - msm_dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0); - msm_dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0); - msm_dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl); - msm_dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_HCTL, 0); - msm_dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F0, display_v_start); - msm_dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end); - msm_dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F1, 0); - msm_dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F1, 0); - msm_dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F0, 0); - msm_dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F0, 0); - msm_dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F1, 0); - msm_dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F1, 0); - msm_dp_write_p0(catalog, MMSS_DP_INTF_POLARITY_CTL, 0); - - msm_dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, - DP_TPG_CHECKERED_RECT_PATTERN); - msm_dp_write_p0(catalog, MMSS_DP_TPG_VIDEO_CONFIG, - DP_TPG_VIDEO_CONFIG_BPP_8BIT | - DP_TPG_VIDEO_CONFIG_RGB); - msm_dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, - DP_BIST_ENABLE_DPBIST_EN); - msm_dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, - DP_TIMING_ENGINE_EN_EN); - drm_dbg_dp(catalog->drm_dev, "%s: enabled tpg\n", __func__); -} - -void msm_dp_catalog_panel_tpg_disable(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - msm_dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, 0x0); - msm_dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, 0x0); - msm_dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0); -} - -static void __iomem *msm_dp_ioremap(struct platform_device *pdev, int idx, size_t *len) -{ - struct resource *res; - void __iomem *base; - - base = devm_platform_get_and_ioremap_resource(pdev, idx, &res); - if (!IS_ERR(base)) - *len = resource_size(res); - - return base; -} - -static int msm_dp_catalog_get_io(struct msm_dp_catalog_private *catalog) -{ - struct platform_device *pdev = to_platform_device(catalog->dev); - struct dss_io_data *dss = &catalog->io; - - dss->ahb.base = msm_dp_ioremap(pdev, 0, &dss->ahb.len); - if (IS_ERR(dss->ahb.base)) - return PTR_ERR(dss->ahb.base); - - dss->aux.base = msm_dp_ioremap(pdev, 1, &dss->aux.len); - if (IS_ERR(dss->aux.base)) { - /* - * The initial binding had a single reg, but in order to - * support variation in the sub-region sizes this was split. - * msm_dp_ioremap() will fail with -EINVAL here if only a single - * reg is specified, so fill in the sub-region offsets and - * lengths based on this single region. - */ - if (PTR_ERR(dss->aux.base) == -EINVAL) { - if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) { - DRM_ERROR("legacy memory region not large enough\n"); - return -EINVAL; - } - - dss->ahb.len = DP_DEFAULT_AHB_SIZE; - dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET; - dss->aux.len = DP_DEFAULT_AUX_SIZE; - dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET; - dss->link.len = DP_DEFAULT_LINK_SIZE; - dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET; - dss->p0.len = DP_DEFAULT_P0_SIZE; - } else { - DRM_ERROR("unable to remap aux region: %pe\n", dss->aux.base); - return PTR_ERR(dss->aux.base); - } - } else { - dss->link.base = msm_dp_ioremap(pdev, 2, &dss->link.len); - if (IS_ERR(dss->link.base)) { - DRM_ERROR("unable to remap link region: %pe\n", dss->link.base); - return PTR_ERR(dss->link.base); - } - - dss->p0.base = msm_dp_ioremap(pdev, 3, &dss->p0.len); - if (IS_ERR(dss->p0.base)) { - DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base); - return PTR_ERR(dss->p0.base); - } - } - - return 0; -} - -struct msm_dp_catalog *msm_dp_catalog_get(struct device *dev) -{ - struct msm_dp_catalog_private *catalog; - int ret; - - catalog = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL); - if (!catalog) - return ERR_PTR(-ENOMEM); - - catalog->dev = dev; - - ret = msm_dp_catalog_get_io(catalog); - if (ret) - return ERR_PTR(ret); - - return &catalog->msm_dp_catalog; -} - -u32 msm_dp_catalog_audio_get_header(struct msm_dp_catalog *msm_dp_catalog, - enum msm_dp_catalog_audio_sdp_type sdp, - enum msm_dp_catalog_audio_header_type header) -{ - struct msm_dp_catalog_private *catalog; - u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; - - catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - sdp_map = catalog->audio_map; - - return msm_dp_read_link(catalog, sdp_map[sdp][header]); -} - -void msm_dp_catalog_audio_set_header(struct msm_dp_catalog *msm_dp_catalog, - enum msm_dp_catalog_audio_sdp_type sdp, - enum msm_dp_catalog_audio_header_type header, - u32 data) -{ - struct msm_dp_catalog_private *catalog; - u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; - - if (!msm_dp_catalog) - return; - - catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - sdp_map = catalog->audio_map; - - msm_dp_write_link(catalog, sdp_map[sdp][header], data); -} - -void msm_dp_catalog_audio_config_acr(struct msm_dp_catalog *msm_dp_catalog, u32 select) -{ - struct msm_dp_catalog_private *catalog; - u32 acr_ctrl; - - if (!msm_dp_catalog) - return; - - catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14); - - drm_dbg_dp(catalog->drm_dev, "select: %#x, acr_ctrl: %#x\n", - select, acr_ctrl); - - msm_dp_write_link(catalog, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl); -} - -void msm_dp_catalog_audio_enable(struct msm_dp_catalog *msm_dp_catalog, bool enable) -{ - struct msm_dp_catalog_private *catalog; - u32 audio_ctrl; - - if (!msm_dp_catalog) - return; - - catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - audio_ctrl = msm_dp_read_link(catalog, MMSS_DP_AUDIO_CFG); - - if (enable) - audio_ctrl |= BIT(0); - else - audio_ctrl &= ~BIT(0); - - drm_dbg_dp(catalog->drm_dev, "dp_audio_cfg = 0x%x\n", audio_ctrl); - - msm_dp_write_link(catalog, MMSS_DP_AUDIO_CFG, audio_ctrl); - /* make sure audio engine is disabled */ - wmb(); -} - -void msm_dp_catalog_audio_config_sdp(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog; - u32 sdp_cfg = 0; - u32 sdp_cfg2 = 0; - - if (!msm_dp_catalog) - return; - - catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - sdp_cfg = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG); - /* AUDIO_TIMESTAMP_SDP_EN */ - sdp_cfg |= BIT(1); - /* AUDIO_STREAM_SDP_EN */ - sdp_cfg |= BIT(2); - /* AUDIO_COPY_MANAGEMENT_SDP_EN */ - sdp_cfg |= BIT(5); - /* AUDIO_ISRC_SDP_EN */ - sdp_cfg |= BIT(6); - /* AUDIO_INFOFRAME_SDP_EN */ - sdp_cfg |= BIT(20); - - drm_dbg_dp(catalog->drm_dev, "sdp_cfg = 0x%x\n", sdp_cfg); - - msm_dp_write_link(catalog, MMSS_DP_SDP_CFG, sdp_cfg); - - sdp_cfg2 = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG2); - /* IFRM_REGSRC -> Do not use reg values */ - sdp_cfg2 &= ~BIT(0); - /* AUDIO_STREAM_HB3_REGSRC-> Do not use reg values */ - sdp_cfg2 &= ~BIT(1); - - drm_dbg_dp(catalog->drm_dev, "sdp_cfg2 = 0x%x\n", sdp_cfg2); - - msm_dp_write_link(catalog, MMSS_DP_SDP_CFG2, sdp_cfg2); -} - -void msm_dp_catalog_audio_init(struct msm_dp_catalog *msm_dp_catalog) -{ - struct msm_dp_catalog_private *catalog; - - static u32 sdp_map[][DP_AUDIO_SDP_HEADER_MAX] = { - { - MMSS_DP_AUDIO_STREAM_0, - MMSS_DP_AUDIO_STREAM_1, - MMSS_DP_AUDIO_STREAM_1, - }, - { - MMSS_DP_AUDIO_TIMESTAMP_0, - MMSS_DP_AUDIO_TIMESTAMP_1, - MMSS_DP_AUDIO_TIMESTAMP_1, - }, - { - MMSS_DP_AUDIO_INFOFRAME_0, - MMSS_DP_AUDIO_INFOFRAME_1, - MMSS_DP_AUDIO_INFOFRAME_1, - }, - { - MMSS_DP_AUDIO_COPYMANAGEMENT_0, - MMSS_DP_AUDIO_COPYMANAGEMENT_1, - MMSS_DP_AUDIO_COPYMANAGEMENT_1, - }, - { - MMSS_DP_AUDIO_ISRC_0, - MMSS_DP_AUDIO_ISRC_1, - MMSS_DP_AUDIO_ISRC_1, - }, - }; - - if (!msm_dp_catalog) - return; - - catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - catalog->audio_map = sdp_map; -} - -void msm_dp_catalog_audio_sfe_level(struct msm_dp_catalog *msm_dp_catalog, u32 safe_to_exit_level) -{ - struct msm_dp_catalog_private *catalog; - u32 mainlink_levels; - - if (!msm_dp_catalog) - return; - - catalog = container_of(msm_dp_catalog, - struct msm_dp_catalog_private, msm_dp_catalog); - - mainlink_levels = msm_dp_read_link(catalog, REG_DP_MAINLINK_LEVELS); - mainlink_levels &= 0xFE0; - mainlink_levels |= safe_to_exit_level; - - drm_dbg_dp(catalog->drm_dev, - "mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n", - mainlink_levels, safe_to_exit_level); - - msm_dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, mainlink_levels); -} diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h deleted file mode 100644 index e932b17eecbf..000000000000 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ /dev/null @@ -1,128 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_CATALOG_H_ -#define _DP_CATALOG_H_ - -#include <drm/drm_modes.h> - -#include "dp_utils.h" -#include "disp/msm_disp_snapshot.h" - -/* interrupts */ -#define DP_INTR_HPD BIT(0) -#define DP_INTR_AUX_XFER_DONE BIT(3) -#define DP_INTR_WRONG_ADDR BIT(6) -#define DP_INTR_TIMEOUT BIT(9) -#define DP_INTR_NACK_DEFER BIT(12) -#define DP_INTR_WRONG_DATA_CNT BIT(15) -#define DP_INTR_I2C_NACK BIT(18) -#define DP_INTR_I2C_DEFER BIT(21) -#define DP_INTR_PLL_UNLOCKED BIT(24) -#define DP_INTR_AUX_ERROR BIT(27) - -#define DP_INTR_READY_FOR_VIDEO BIT(0) -#define DP_INTR_IDLE_PATTERN_SENT BIT(3) -#define DP_INTR_FRAME_END BIT(6) -#define DP_INTR_CRC_UPDATED BIT(9) - -#define DP_HW_VERSION_1_0 0x10000000 -#define DP_HW_VERSION_1_2 0x10020000 - -enum msm_dp_catalog_audio_sdp_type { - DP_AUDIO_SDP_STREAM, - DP_AUDIO_SDP_TIMESTAMP, - DP_AUDIO_SDP_INFOFRAME, - DP_AUDIO_SDP_COPYMANAGEMENT, - DP_AUDIO_SDP_ISRC, - DP_AUDIO_SDP_MAX, -}; - -enum msm_dp_catalog_audio_header_type { - DP_AUDIO_SDP_HEADER_1, - DP_AUDIO_SDP_HEADER_2, - DP_AUDIO_SDP_HEADER_3, - DP_AUDIO_SDP_HEADER_MAX, -}; - -struct msm_dp_catalog { - bool wide_bus_en; -}; - -/* Debug module */ -void msm_dp_catalog_snapshot(struct msm_dp_catalog *msm_dp_catalog, struct msm_disp_state *disp_state); - -/* AUX APIs */ -u32 msm_dp_catalog_aux_read_data(struct msm_dp_catalog *msm_dp_catalog); -int msm_dp_catalog_aux_write_data(struct msm_dp_catalog *msm_dp_catalog, u32 data); -int msm_dp_catalog_aux_write_trans(struct msm_dp_catalog *msm_dp_catalog, u32 data); -int msm_dp_catalog_aux_clear_trans(struct msm_dp_catalog *msm_dp_catalog, bool read); -int msm_dp_catalog_aux_clear_hw_interrupts(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_aux_reset(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_aux_enable(struct msm_dp_catalog *msm_dp_catalog, bool enable); -int msm_dp_catalog_aux_wait_for_hpd_connect_state(struct msm_dp_catalog *msm_dp_catalog, - unsigned long wait_us); -u32 msm_dp_catalog_aux_get_irq(struct msm_dp_catalog *msm_dp_catalog); - -/* DP Controller APIs */ -void msm_dp_catalog_ctrl_state_ctrl(struct msm_dp_catalog *msm_dp_catalog, u32 state); -void msm_dp_catalog_ctrl_config_ctrl(struct msm_dp_catalog *msm_dp_catalog, u32 config); -void msm_dp_catalog_ctrl_lane_mapping(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_ctrl_mainlink_ctrl(struct msm_dp_catalog *msm_dp_catalog, bool enable); -void msm_dp_catalog_ctrl_psr_mainlink_enable(struct msm_dp_catalog *msm_dp_catalog, bool enable); -void msm_dp_catalog_setup_peripheral_flush(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_ctrl_config_misc(struct msm_dp_catalog *msm_dp_catalog, u32 cc, u32 tb); -void msm_dp_catalog_ctrl_config_msa(struct msm_dp_catalog *msm_dp_catalog, u32 rate, - u32 stream_rate_khz, bool is_ycbcr_420); -int msm_dp_catalog_ctrl_set_pattern_state_bit(struct msm_dp_catalog *msm_dp_catalog, u32 pattern); -u32 msm_dp_catalog_hw_revision(const struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_ctrl_reset(struct msm_dp_catalog *msm_dp_catalog); -bool msm_dp_catalog_ctrl_mainlink_ready(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_ctrl_enable_irq(struct msm_dp_catalog *msm_dp_catalog, bool enable); -void msm_dp_catalog_hpd_config_intr(struct msm_dp_catalog *msm_dp_catalog, - u32 intr_mask, bool en); -void msm_dp_catalog_ctrl_hpd_enable(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_ctrl_hpd_disable(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_ctrl_config_psr(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_ctrl_set_psr(struct msm_dp_catalog *msm_dp_catalog, bool enter); -u32 msm_dp_catalog_link_is_connected(struct msm_dp_catalog *msm_dp_catalog); -u32 msm_dp_catalog_hpd_get_intr_status(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_ctrl_phy_reset(struct msm_dp_catalog *msm_dp_catalog); -int msm_dp_catalog_ctrl_get_interrupt(struct msm_dp_catalog *msm_dp_catalog); -u32 msm_dp_catalog_ctrl_read_psr_interrupt_status(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_ctrl_update_transfer_unit(struct msm_dp_catalog *msm_dp_catalog, - u32 msm_dp_tu, u32 valid_boundary, - u32 valid_boundary2); -void msm_dp_catalog_ctrl_send_phy_pattern(struct msm_dp_catalog *msm_dp_catalog, - u32 pattern); -u32 msm_dp_catalog_ctrl_read_phy_pattern(struct msm_dp_catalog *msm_dp_catalog); - -/* DP Panel APIs */ -int msm_dp_catalog_panel_timing_cfg(struct msm_dp_catalog *msm_dp_catalog, u32 total, - u32 sync_start, u32 width_blanking, u32 msm_dp_active); -void msm_dp_catalog_panel_enable_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog, struct dp_sdp *vsc_sdp); -void msm_dp_catalog_panel_disable_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_dump_regs(struct msm_dp_catalog *msm_dp_catalog); -void msm_dp_catalog_panel_tpg_enable(struct msm_dp_catalog *msm_dp_catalog, - struct drm_display_mode *drm_mode); -void msm_dp_catalog_panel_tpg_disable(struct msm_dp_catalog *msm_dp_catalog); - -struct msm_dp_catalog *msm_dp_catalog_get(struct device *dev); - -/* DP Audio APIs */ -u32 msm_dp_catalog_audio_get_header(struct msm_dp_catalog *msm_dp_catalog, - enum msm_dp_catalog_audio_sdp_type sdp, - enum msm_dp_catalog_audio_header_type header); -void msm_dp_catalog_audio_set_header(struct msm_dp_catalog *msm_dp_catalog, - enum msm_dp_catalog_audio_sdp_type sdp, - enum msm_dp_catalog_audio_header_type header, - u32 data); -void msm_dp_catalog_audio_config_acr(struct msm_dp_catalog *catalog, u32 select); -void msm_dp_catalog_audio_enable(struct msm_dp_catalog *catalog, bool enable); -void msm_dp_catalog_audio_config_sdp(struct msm_dp_catalog *catalog); -void msm_dp_catalog_audio_init(struct msm_dp_catalog *catalog); -void msm_dp_catalog_audio_sfe_level(struct msm_dp_catalog *catalog, u32 safe_to_exit_level); - -#endif /* _DP_CATALOG_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index bc2ca8133b79..cbcc7c2f0ffc 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -6,13 +6,18 @@ #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ #include <linux/types.h> +#include <linux/clk.h> #include <linux/completion.h> #include <linux/delay.h> +#include <linux/iopoll.h> #include <linux/phy/phy.h> #include <linux/phy/phy-dp.h> #include <linux/pm_opp.h> +#include <linux/rational.h> +#include <linux/string_choices.h> #include <drm/display/drm_dp_helper.h> +#include <drm/drm_device.h> #include <drm/drm_fixed.h> #include <drm/drm_print.h> @@ -20,11 +25,46 @@ #include "dp_ctrl.h" #include "dp_link.h" +#define POLLING_SLEEP_US 1000 +#define POLLING_TIMEOUT_US 10000 + #define DP_KHZ_TO_HZ 1000 #define IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES (30 * HZ / 1000) /* 30 ms */ #define PSR_OPERATION_COMPLETION_TIMEOUT_JIFFIES (300 * HZ / 1000) /* 300 ms */ #define WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES (HZ / 2) +#define DP_INTERRUPT_STATUS_ACK_SHIFT 1 +#define DP_INTERRUPT_STATUS_MASK_SHIFT 2 + +#define DP_INTERRUPT_STATUS1 \ + (DP_INTR_AUX_XFER_DONE| \ + DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \ + DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \ + DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \ + DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR) + +#define DP_INTERRUPT_STATUS1_ACK \ + (DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_ACK_SHIFT) +#define DP_INTERRUPT_STATUS1_MASK \ + (DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_MASK_SHIFT) + +#define DP_INTERRUPT_STATUS2 \ + (DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \ + DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED) + +#define DP_INTERRUPT_STATUS2_ACK \ + (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_ACK_SHIFT) +#define DP_INTERRUPT_STATUS2_MASK \ + (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT) + +#define DP_INTERRUPT_STATUS4 \ + (PSR_UPDATE_INT | PSR_CAPTURE_INT | PSR_EXIT_INT | \ + PSR_UPDATE_ERROR_INT | PSR_WAKE_ERROR_INT) + +#define DP_INTERRUPT_MASK4 \ + (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \ + PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK) + #define DP_CTRL_INTR_READY_FOR_VIDEO BIT(0) #define DP_CTRL_INTR_IDLE_PATTERN_SENT BIT(3) @@ -76,7 +116,8 @@ struct msm_dp_ctrl_private { struct drm_dp_aux *aux; struct msm_dp_panel *panel; struct msm_dp_link *link; - struct msm_dp_catalog *catalog; + void __iomem *ahb_base; + void __iomem *link_base; struct phy *phy; @@ -94,11 +135,43 @@ struct msm_dp_ctrl_private { struct completion psr_op_comp; struct completion video_comp; + u32 hw_revision; + bool core_clks_on; bool link_clks_on; bool stream_clks_on; }; +static inline u32 msm_dp_read_ahb(const struct msm_dp_ctrl_private *ctrl, u32 offset) +{ + return readl_relaxed(ctrl->ahb_base + offset); +} + +static inline void msm_dp_write_ahb(struct msm_dp_ctrl_private *ctrl, + u32 offset, u32 data) +{ + /* + * To make sure phy reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + writel(data, ctrl->ahb_base + offset); +} + +static inline u32 msm_dp_read_link(struct msm_dp_ctrl_private *ctrl, u32 offset) +{ + return readl_relaxed(ctrl->link_base + offset); +} + +static inline void msm_dp_write_link(struct msm_dp_ctrl_private *ctrl, + u32 offset, u32 data) +{ + /* + * To make sure link reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + writel(data, ctrl->link_base + offset); +} + static int msm_dp_aux_link_configure(struct drm_dp_aux *aux, struct msm_dp_link_info *link) { @@ -118,6 +191,179 @@ static int msm_dp_aux_link_configure(struct drm_dp_aux *aux, return 0; } +/* + * NOTE: resetting DP controller will also clear any pending HPD related interrupts + */ +void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl) +{ + struct msm_dp_ctrl_private *ctrl = + container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + u32 sw_reset; + + sw_reset = msm_dp_read_ahb(ctrl, REG_DP_SW_RESET); + + sw_reset |= DP_SW_RESET; + msm_dp_write_ahb(ctrl, REG_DP_SW_RESET, sw_reset); + usleep_range(1000, 1100); /* h/w recommended delay */ + + sw_reset &= ~DP_SW_RESET; + msm_dp_write_ahb(ctrl, REG_DP_SW_RESET, sw_reset); + + if (!ctrl->hw_revision) { + ctrl->hw_revision = msm_dp_read_ahb(ctrl, REG_DP_HW_VERSION); + ctrl->panel->hw_revision = ctrl->hw_revision; + } +} + +static u32 msm_dp_ctrl_get_aux_interrupt(struct msm_dp_ctrl_private *ctrl) +{ + u32 intr, intr_ack; + + intr = msm_dp_read_ahb(ctrl, REG_DP_INTR_STATUS); + intr &= ~DP_INTERRUPT_STATUS1_MASK; + intr_ack = (intr & DP_INTERRUPT_STATUS1) + << DP_INTERRUPT_STATUS_ACK_SHIFT; + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS, + intr_ack | DP_INTERRUPT_STATUS1_MASK); + + return intr; + +} + +static u32 msm_dp_ctrl_get_interrupt(struct msm_dp_ctrl_private *ctrl) +{ + u32 intr, intr_ack; + + intr = msm_dp_read_ahb(ctrl, REG_DP_INTR_STATUS2); + intr &= ~DP_INTERRUPT_STATUS2_MASK; + intr_ack = (intr & DP_INTERRUPT_STATUS2) + << DP_INTERRUPT_STATUS_ACK_SHIFT; + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2, + intr_ack | DP_INTERRUPT_STATUS2_MASK); + + return intr; +} + +void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl) +{ + struct msm_dp_ctrl_private *ctrl = + container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS, + DP_INTERRUPT_STATUS1_MASK); + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2, + DP_INTERRUPT_STATUS2_MASK); +} + +void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl) +{ + struct msm_dp_ctrl_private *ctrl = + container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS, 0x00); + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2, 0x00); +} + +static u32 msm_dp_ctrl_get_psr_interrupt(struct msm_dp_ctrl_private *ctrl) +{ + u32 intr, intr_ack; + + intr = msm_dp_read_ahb(ctrl, REG_DP_INTR_STATUS4); + intr_ack = (intr & DP_INTERRUPT_STATUS4) + << DP_INTERRUPT_STATUS_ACK_SHIFT; + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS4, intr_ack); + + return intr; +} + +static void msm_dp_ctrl_config_psr_interrupt(struct msm_dp_ctrl_private *ctrl) +{ + msm_dp_write_ahb(ctrl, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4); +} + +static void msm_dp_ctrl_psr_mainlink_enable(struct msm_dp_ctrl_private *ctrl) +{ + u32 val; + + val = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL); + val |= DP_MAINLINK_CTRL_ENABLE; + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, val); +} + +static void msm_dp_ctrl_psr_mainlink_disable(struct msm_dp_ctrl_private *ctrl) +{ + u32 val; + + val = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL); + val &= ~DP_MAINLINK_CTRL_ENABLE; + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, val); +} + +static void msm_dp_ctrl_mainlink_enable(struct msm_dp_ctrl_private *ctrl) +{ + u32 mainlink_ctrl; + + drm_dbg_dp(ctrl->drm_dev, "enable\n"); + + mainlink_ctrl = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL); + + mainlink_ctrl &= ~(DP_MAINLINK_CTRL_RESET | + DP_MAINLINK_CTRL_ENABLE); + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl); + + mainlink_ctrl |= DP_MAINLINK_CTRL_RESET; + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl); + + mainlink_ctrl &= ~DP_MAINLINK_CTRL_RESET; + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl); + + mainlink_ctrl |= (DP_MAINLINK_CTRL_ENABLE | + DP_MAINLINK_FB_BOUNDARY_SEL); + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl); +} + +static void msm_dp_ctrl_mainlink_disable(struct msm_dp_ctrl_private *ctrl) +{ + u32 mainlink_ctrl; + + drm_dbg_dp(ctrl->drm_dev, "disable\n"); + + mainlink_ctrl = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL); + mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE; + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl); +} + +static void msm_dp_setup_peripheral_flush(struct msm_dp_ctrl_private *ctrl) +{ + u32 mainlink_ctrl; + + mainlink_ctrl = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL); + + if (ctrl->hw_revision >= DP_HW_VERSION_1_2) + mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE; + else + mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_UPDATE_SDP; + + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl); +} + +static bool msm_dp_ctrl_mainlink_ready(struct msm_dp_ctrl_private *ctrl) +{ + u32 data; + int ret; + + /* Poll for mainlink ready status */ + ret = readl_poll_timeout(ctrl->link_base + REG_DP_MAINLINK_READY, + data, data & DP_MAINLINK_READY_FOR_VIDEO, + POLLING_SLEEP_US, POLLING_TIMEOUT_US); + if (ret < 0) { + DRM_ERROR("mainlink not ready\n"); + return false; + } + + return true; +} + void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl) { struct msm_dp_ctrl_private *ctrl; @@ -125,7 +371,7 @@ void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); reinit_completion(&ctrl->idle_comp); - msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_PUSH_IDLE); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_PUSH_IDLE); if (!wait_for_completion_timeout(&ctrl->idle_comp, IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES)) @@ -170,24 +416,50 @@ static void msm_dp_ctrl_config_ctrl(struct msm_dp_ctrl_private *ctrl) if (ctrl->panel->psr_cap.version) config |= DP_CONFIGURATION_CTRL_SEND_VSC; - msm_dp_catalog_ctrl_config_ctrl(ctrl->catalog, config); + drm_dbg_dp(ctrl->drm_dev, "DP_CONFIGURATION_CTRL=0x%x\n", config); + + msm_dp_write_link(ctrl, REG_DP_CONFIGURATION_CTRL, config); +} + +static void msm_dp_ctrl_lane_mapping(struct msm_dp_ctrl_private *ctrl) +{ + u32 *lane_map = ctrl->link->lane_map; + u32 ln_mapping; + + ln_mapping = lane_map[0] << LANE0_MAPPING_SHIFT; + ln_mapping |= lane_map[1] << LANE1_MAPPING_SHIFT; + ln_mapping |= lane_map[2] << LANE2_MAPPING_SHIFT; + ln_mapping |= lane_map[3] << LANE3_MAPPING_SHIFT; + + msm_dp_write_link(ctrl, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING, + ln_mapping); } static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl) { - u32 cc, tb; + u32 colorimetry_cfg, test_bits_depth, misc_val; - msm_dp_catalog_ctrl_lane_mapping(ctrl->catalog); - msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true); - msm_dp_catalog_setup_peripheral_flush(ctrl->catalog); + msm_dp_ctrl_lane_mapping(ctrl); + msm_dp_setup_peripheral_flush(ctrl); msm_dp_ctrl_config_ctrl(ctrl); - tb = msm_dp_link_get_test_bits_depth(ctrl->link, - ctrl->panel->msm_dp_mode.bpp); - cc = msm_dp_link_get_colorimetry_config(ctrl->link); - msm_dp_catalog_ctrl_config_misc(ctrl->catalog, cc, tb); - msm_dp_panel_timing_cfg(ctrl->panel); + test_bits_depth = msm_dp_link_get_test_bits_depth(ctrl->link, ctrl->panel->msm_dp_mode.bpp); + colorimetry_cfg = msm_dp_link_get_colorimetry_config(ctrl->link); + + misc_val = msm_dp_read_link(ctrl, REG_DP_MISC1_MISC0); + + /* clear bpp bits */ + misc_val &= ~(0x07 << DP_MISC0_TEST_BITS_DEPTH_SHIFT); + misc_val |= colorimetry_cfg << DP_MISC0_COLORIMETRY_CFG_SHIFT; + misc_val |= test_bits_depth << DP_MISC0_TEST_BITS_DEPTH_SHIFT; + /* Configure clock to synchronous mode */ + misc_val |= DP_MISC0_SYNCHRONOUS_CLK; + + drm_dbg_dp(ctrl->drm_dev, "misc settings = 0x%x\n", misc_val); + msm_dp_write_link(ctrl, REG_DP_MISC1_MISC0, misc_val); + + msm_dp_panel_timing_cfg(ctrl->panel, ctrl->msm_dp_ctrl.wide_bus_en); } /* @@ -1003,8 +1275,9 @@ static void msm_dp_ctrl_setup_tr_unit(struct msm_dp_ctrl_private *ctrl) pr_debug("dp_tu=0x%x, valid_boundary=0x%x, valid_boundary2=0x%x\n", msm_dp_tu, valid_boundary, valid_boundary2); - msm_dp_catalog_ctrl_update_transfer_unit(ctrl->catalog, - msm_dp_tu, valid_boundary, valid_boundary2); + msm_dp_write_link(ctrl, REG_DP_VALID_BOUNDARY, valid_boundary); + msm_dp_write_link(ctrl, REG_DP_TU, msm_dp_tu); + msm_dp_write_link(ctrl, REG_DP_VALID_BOUNDARY_2, valid_boundary2); } static int msm_dp_ctrl_wait4video_ready(struct msm_dp_ctrl_private *ctrl) @@ -1034,10 +1307,12 @@ static int msm_dp_ctrl_set_vx_px(struct msm_dp_ctrl_private *ctrl, return 0; } -static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_update_phy_vx_px(struct msm_dp_ctrl_private *ctrl, + enum drm_dp_phy dp_phy) { struct msm_dp_link *link = ctrl->link; - int ret = 0, lane, lane_cnt; + int lane, lane_cnt, reg; + int ret = 0; u8 buf[4]; u32 max_level_reached = 0; u32 voltage_swing_level = link->phy_params.v_level; @@ -1075,8 +1350,13 @@ static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) drm_dbg_dp(ctrl->drm_dev, "sink: p|v=0x%x\n", voltage_swing_level | pre_emphasis_level); - ret = drm_dp_dpcd_write(ctrl->aux, DP_TRAINING_LANE0_SET, - buf, lane_cnt); + + if (dp_phy == DP_PHY_DPRX) + reg = DP_TRAINING_LANE0_SET; + else + reg = DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy); + + ret = drm_dp_dpcd_write(ctrl->aux, reg, buf, lane_cnt); if (ret == lane_cnt) ret = 0; @@ -1084,9 +1364,10 @@ static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) } static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl, - u8 pattern) + u8 pattern, enum drm_dp_phy dp_phy) { u8 buf; + int reg; int ret = 0; drm_dbg_dp(ctrl->drm_dev, "sink: pattern=%x\n", pattern); @@ -1096,51 +1377,71 @@ static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl, if (pattern && pattern != DP_TRAINING_PATTERN_4) buf |= DP_LINK_SCRAMBLING_DISABLE; - ret = drm_dp_dpcd_writeb(ctrl->aux, DP_TRAINING_PATTERN_SET, buf); + if (dp_phy == DP_PHY_DPRX) + reg = DP_TRAINING_PATTERN_SET; + else + reg = DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy); + + ret = drm_dp_dpcd_writeb(ctrl->aux, reg, buf); return ret == 1; } -static int msm_dp_ctrl_read_link_status(struct msm_dp_ctrl_private *ctrl, - u8 *link_status) +static int msm_dp_ctrl_set_pattern_state_bit(struct msm_dp_ctrl_private *ctrl, + u32 state_bit) { - int ret = 0, len; + int bit, ret; + u32 data; - len = drm_dp_dpcd_read_link_status(ctrl->aux, link_status); - if (len != DP_LINK_STATUS_SIZE) { - DRM_ERROR("DP link status read failed, err: %d\n", len); - ret = -EINVAL; + bit = BIT(state_bit - 1); + drm_dbg_dp(ctrl->drm_dev, "hw: bit=%d train=%d\n", bit, state_bit); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, bit); + + bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT; + + /* Poll for mainlink ready status */ + ret = readx_poll_timeout(readl, ctrl->link_base + REG_DP_MAINLINK_READY, + data, data & bit, + POLLING_SLEEP_US, POLLING_TIMEOUT_US); + if (ret < 0) { + DRM_ERROR("set state_bit for link_train=%d failed\n", state_bit); + return ret; } - return ret; + return 0; } static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, - int *training_step) + int *training_step, enum drm_dp_phy dp_phy) { + int delay_us; int tries, old_v_level, ret = 0; u8 link_status[DP_LINK_STATUS_SIZE]; int const maximum_retries = 4; - msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); + delay_us = drm_dp_read_clock_recovery_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); *training_step = DP_TRAINING_1; - ret = msm_dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, 1); + ret = msm_dp_ctrl_set_pattern_state_bit(ctrl, 1); if (ret) return ret; msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 | - DP_LINK_SCRAMBLING_DISABLE); + DP_LINK_SCRAMBLING_DISABLE, dp_phy); - ret = msm_dp_ctrl_update_vx_px(ctrl); + msm_dp_link_reset_phy_params_vx_px(ctrl->link); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; tries = 0; old_v_level = ctrl->link->phy_params.v_level; for (tries = 0; tries < maximum_retries; tries++) { - drm_dp_link_train_clock_recovery_delay(ctrl->aux, ctrl->panel->dpcd); + fsleep(delay_us); - ret = msm_dp_ctrl_read_link_status(ctrl, link_status); + ret = drm_dp_dpcd_read_phy_link_status(ctrl->aux, dp_phy, link_status); if (ret) return ret; @@ -1161,7 +1462,7 @@ static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, } msm_dp_link_adjust_levels(ctrl->link, link_status); - ret = msm_dp_ctrl_update_vx_px(ctrl); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; } @@ -1213,22 +1514,32 @@ static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl) return 0; } -static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl) +static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, + enum drm_dp_phy dp_phy) { - msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE); - drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd); + int delay_us; + + msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE, dp_phy); + + delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + fsleep(delay_us); } static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, - int *training_step) + int *training_step, enum drm_dp_phy dp_phy) { + int delay_us; int tries = 0, ret = 0; u8 pattern; u32 state_ctrl_bit; int const maximum_retries = 5; u8 link_status[DP_LINK_STATUS_SIZE]; - msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); + delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); *training_step = DP_TRAINING_2; @@ -1243,16 +1554,16 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, state_ctrl_bit = 2; } - ret = msm_dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, state_ctrl_bit); + ret = msm_dp_ctrl_set_pattern_state_bit(ctrl, state_ctrl_bit); if (ret) return ret; - msm_dp_ctrl_train_pattern_set(ctrl, pattern); + msm_dp_ctrl_train_pattern_set(ctrl, pattern, dp_phy); for (tries = 0; tries <= maximum_retries; tries++) { - drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd); + fsleep(delay_us); - ret = msm_dp_ctrl_read_link_status(ctrl, link_status); + ret = drm_dp_dpcd_read_phy_link_status(ctrl->aux, dp_phy, link_status); if (ret) return ret; @@ -1262,7 +1573,7 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, } msm_dp_link_adjust_levels(ctrl->link, link_status); - ret = msm_dp_ctrl_update_vx_px(ctrl); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; @@ -1271,9 +1582,32 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, return -ETIMEDOUT; } +static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, + int *training_step, enum drm_dp_phy dp_phy) +{ + int ret; + + ret = msm_dp_ctrl_link_train_1(ctrl, training_step, dp_phy); + if (ret) { + DRM_ERROR("link training #1 on phy %d failed. ret=%d\n", dp_phy, ret); + return ret; + } + drm_dbg_dp(ctrl->drm_dev, "link training #1 on phy %d successful\n", dp_phy); + + ret = msm_dp_ctrl_link_train_2(ctrl, training_step, dp_phy); + if (ret) { + DRM_ERROR("link training #2 on phy %d failed. ret=%d\n", dp_phy, ret); + return ret; + } + drm_dbg_dp(ctrl->drm_dev, "link training #2 on phy %d successful\n", dp_phy); + + return 0; +} + static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, int *training_step) { + int i; int ret = 0; const u8 *dpcd = ctrl->panel->dpcd; u8 encoding[] = { 0, DP_SET_ANSI_8B10B }; @@ -1286,8 +1620,6 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, link_info.rate = ctrl->link->link_params.rate; link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING; - msm_dp_link_reset_phy_params_vx_px(ctrl->link); - msm_dp_aux_link_configure(ctrl->aux, &link_info); if (drm_dp_max_downspread(dpcd)) @@ -1302,26 +1634,29 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, &assr, 1); } - ret = msm_dp_ctrl_link_train_1(ctrl, training_step); + for (i = ctrl->link->lttpr_count - 1; i >= 0; i--) { + enum drm_dp_phy dp_phy = DP_PHY_LTTPR(i); + + ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, dp_phy); + msm_dp_ctrl_clear_training_pattern(ctrl, dp_phy); + + if (ret) + break; + } + if (ret) { - DRM_ERROR("link training #1 failed. ret=%d\n", ret); + DRM_ERROR("link training of LTTPR(s) failed. ret=%d\n", ret); goto end; } - /* print success info as this is a result of user initiated action */ - drm_dbg_dp(ctrl->drm_dev, "link training #1 successful\n"); - - ret = msm_dp_ctrl_link_train_2(ctrl, training_step); + ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, DP_PHY_DPRX); if (ret) { - DRM_ERROR("link training #2 failed. ret=%d\n", ret); + DRM_ERROR("link training on sink failed. ret=%d\n", ret); goto end; } - /* print success info as this is a result of user initiated action */ - drm_dbg_dp(ctrl->drm_dev, "link training #2 successful\n"); - end: - msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); return ret; } @@ -1331,7 +1666,7 @@ static int msm_dp_ctrl_setup_main_link(struct msm_dp_ctrl_private *ctrl, { int ret = 0; - msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true); + msm_dp_ctrl_mainlink_enable(ctrl); if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) return ret; @@ -1367,9 +1702,9 @@ int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "enable core clocks \n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - ctrl->stream_clks_on ? "on" : "off", - ctrl->link_clks_on ? "on" : "off", - ctrl->core_clks_on ? "on" : "off"); + str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->link_clks_on), + str_on_off(ctrl->core_clks_on)); return 0; } @@ -1386,9 +1721,9 @@ void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "disable core clocks \n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - ctrl->stream_clks_on ? "on" : "off", - ctrl->link_clks_on ? "on" : "off", - ctrl->core_clks_on ? "on" : "off"); + str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->link_clks_on), + str_on_off(ctrl->core_clks_on)); } static int msm_dp_ctrl_link_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl) @@ -1417,9 +1752,9 @@ static int msm_dp_ctrl_link_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "enable link clocks\n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - ctrl->stream_clks_on ? "on" : "off", - ctrl->link_clks_on ? "on" : "off", - ctrl->core_clks_on ? "on" : "off"); + str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->link_clks_on), + str_on_off(ctrl->core_clks_on)); return 0; } @@ -1436,9 +1771,9 @@ static void msm_dp_ctrl_link_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "disabled link clocks\n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - ctrl->stream_clks_on ? "on" : "off", - ctrl->link_clks_on ? "on" : "off", - ctrl->core_clks_on ? "on" : "off"); + str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->link_clks_on), + str_on_off(ctrl->core_clks_on)); } static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl) @@ -1464,33 +1799,55 @@ static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl) return ret; } -void msm_dp_ctrl_reset_irq_ctrl(struct msm_dp_ctrl *msm_dp_ctrl, bool enable) +static void msm_dp_ctrl_enable_sdp(struct msm_dp_ctrl_private *ctrl) { - struct msm_dp_ctrl_private *ctrl; + /* trigger sdp */ + msm_dp_write_link(ctrl, MMSS_DP_SDP_CFG3, UPDATE_SDP); + msm_dp_write_link(ctrl, MMSS_DP_SDP_CFG3, 0x0); +} - ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); +static void msm_dp_ctrl_psr_enter(struct msm_dp_ctrl_private *ctrl) +{ + u32 cmd; - msm_dp_catalog_ctrl_reset(ctrl->catalog); + cmd = msm_dp_read_link(ctrl, REG_PSR_CMD); - /* - * all dp controller programmable registers will not - * be reset to default value after DP_SW_RESET - * therefore interrupt mask bits have to be updated - * to enable/disable interrupts - */ - msm_dp_catalog_ctrl_enable_irq(ctrl->catalog, enable); + cmd &= ~(PSR_ENTER | PSR_EXIT); + cmd |= PSR_ENTER; + + msm_dp_ctrl_enable_sdp(ctrl); + msm_dp_write_link(ctrl, REG_PSR_CMD, cmd); +} + +static void msm_dp_ctrl_psr_exit(struct msm_dp_ctrl_private *ctrl) +{ + u32 cmd; + + cmd = msm_dp_read_link(ctrl, REG_PSR_CMD); + + cmd &= ~(PSR_ENTER | PSR_EXIT); + cmd |= PSR_EXIT; + + msm_dp_ctrl_enable_sdp(ctrl); + msm_dp_write_link(ctrl, REG_PSR_CMD, cmd); } void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl) { - u8 cfg; struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + u32 cfg; if (!ctrl->panel->psr_cap.version) return; - msm_dp_catalog_ctrl_config_psr(ctrl->catalog); + /* enable PSR1 function */ + cfg = msm_dp_read_link(ctrl, REG_PSR_CONFIG); + cfg |= PSR1_SUPPORTED; + msm_dp_write_link(ctrl, REG_PSR_CONFIG, cfg); + + msm_dp_ctrl_config_psr_interrupt(ctrl); + msm_dp_ctrl_enable_sdp(ctrl); cfg = DP_PSR_ENABLE; drm_dp_dpcd_write(ctrl->aux, DP_PSR_EN_CFG, &cfg, 1); @@ -1516,29 +1873,37 @@ void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, bool enter) */ if (enter) { reinit_completion(&ctrl->psr_op_comp); - msm_dp_catalog_ctrl_set_psr(ctrl->catalog, true); + msm_dp_ctrl_psr_enter(ctrl); if (!wait_for_completion_timeout(&ctrl->psr_op_comp, PSR_OPERATION_COMPLETION_TIMEOUT_JIFFIES)) { DRM_ERROR("PSR_ENTRY timedout\n"); - msm_dp_catalog_ctrl_set_psr(ctrl->catalog, false); + msm_dp_ctrl_psr_exit(ctrl); return; } msm_dp_ctrl_push_idle(msm_dp_ctrl); - msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); - msm_dp_catalog_ctrl_psr_mainlink_enable(ctrl->catalog, false); + msm_dp_ctrl_psr_mainlink_disable(ctrl); } else { - msm_dp_catalog_ctrl_psr_mainlink_enable(ctrl->catalog, true); + msm_dp_ctrl_psr_mainlink_enable(ctrl); - msm_dp_catalog_ctrl_set_psr(ctrl->catalog, false); - msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO); + msm_dp_ctrl_psr_exit(ctrl); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); msm_dp_ctrl_wait4video_ready(ctrl); - msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); } } +static void msm_dp_ctrl_phy_reset(struct msm_dp_ctrl_private *ctrl) +{ + msm_dp_write_ahb(ctrl, REG_DP_PHY_CTRL, + DP_PHY_CTRL_SW_RESET | DP_PHY_CTRL_SW_RESET_PLL); + usleep_range(1000, 1100); /* h/w recommended delay */ + msm_dp_write_ahb(ctrl, REG_DP_PHY_CTRL, 0x0); +} + void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl) { struct msm_dp_ctrl_private *ctrl; @@ -1547,7 +1912,7 @@ void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); phy = ctrl->phy; - msm_dp_catalog_ctrl_phy_reset(ctrl->catalog); + msm_dp_ctrl_phy_reset(ctrl); phy_init(phy); drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n", @@ -1562,7 +1927,7 @@ void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); phy = ctrl->phy; - msm_dp_catalog_ctrl_phy_reset(ctrl->catalog); + msm_dp_ctrl_phy_reset(ctrl); phy_exit(phy); drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n", phy, phy->init_count, phy->power_count); @@ -1573,7 +1938,7 @@ static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) struct phy *phy = ctrl->phy; int ret = 0; - msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); + msm_dp_ctrl_mainlink_disable(ctrl); ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; phy_configure(phy, &ctrl->phy_opts); /* @@ -1604,9 +1969,9 @@ static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) phy = ctrl->phy; - msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); + msm_dp_ctrl_mainlink_disable(ctrl); - msm_dp_catalog_ctrl_reset(ctrl->catalog); + msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl); dev_pm_opp_set_rate(ctrl->dev, 0); msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); @@ -1636,15 +2001,98 @@ static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl) if (ret) goto end; - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); - msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); ret = msm_dp_ctrl_wait4video_ready(ctrl); end: return ret; } +#define SCRAMBLER_RESET_COUNT_VALUE 0xFC + +static void msm_dp_ctrl_send_phy_pattern(struct msm_dp_ctrl_private *ctrl, + u32 pattern) +{ + u32 value = 0x0; + + /* Make sure to clear the current pattern before starting a new one */ + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0x0); + + drm_dbg_dp(ctrl->drm_dev, "pattern: %#x\n", pattern); + switch (pattern) { + case DP_PHY_TEST_PATTERN_D10_2: + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_TRAINING_PATTERN1); + break; + + case DP_PHY_TEST_PATTERN_ERROR_COUNT: + value &= ~(1 << 16); + msm_dp_write_link(ctrl, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, + value); + value |= SCRAMBLER_RESET_COUNT_VALUE; + msm_dp_write_link(ctrl, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, + value); + msm_dp_write_link(ctrl, REG_DP_MAINLINK_LEVELS, + DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); + break; + + case DP_PHY_TEST_PATTERN_PRBS7: + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_PRBS7); + break; + + case DP_PHY_TEST_PATTERN_80BIT_CUSTOM: + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN); + /* 00111110000011111000001111100000 */ + msm_dp_write_link(ctrl, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0, + 0x3E0F83E0); + /* 00001111100000111110000011111000 */ + msm_dp_write_link(ctrl, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1, + 0x0F83E0F8); + /* 1111100000111110 */ + msm_dp_write_link(ctrl, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2, + 0x0000F83E); + break; + + case DP_PHY_TEST_PATTERN_CP2520: + value = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL); + value &= ~DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER; + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, value); + + value = DP_HBR2_ERM_PATTERN; + msm_dp_write_link(ctrl, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, + value); + value |= SCRAMBLER_RESET_COUNT_VALUE; + msm_dp_write_link(ctrl, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, + value); + msm_dp_write_link(ctrl, REG_DP_MAINLINK_LEVELS, + DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); + value = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL); + value |= DP_MAINLINK_CTRL_ENABLE; + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, value); + break; + + case DP_PHY_TEST_PATTERN_SEL_MASK: + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, + DP_MAINLINK_CTRL_ENABLE); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_TRAINING_PATTERN4); + break; + + default: + drm_dbg_dp(ctrl->drm_dev, + "No valid test pattern requested: %#x\n", pattern); + break; + } +} + static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl) { bool success = false; @@ -1659,11 +2107,11 @@ static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl) DRM_ERROR("Failed to set v/p levels\n"); return false; } - msm_dp_catalog_ctrl_send_phy_pattern(ctrl->catalog, pattern_requested); - msm_dp_ctrl_update_vx_px(ctrl); + msm_dp_ctrl_send_phy_pattern(ctrl, pattern_requested); + msm_dp_ctrl_update_phy_vx_px(ctrl, DP_PHY_DPRX); msm_dp_link_send_test_response(ctrl->link); - pattern_sent = msm_dp_catalog_ctrl_read_phy_pattern(ctrl->catalog); + pattern_sent = msm_dp_read_link(ctrl, REG_DP_MAINLINK_READY); switch (pattern_sent) { case MR_LINK_TRAINING1: @@ -1805,7 +2253,7 @@ static bool msm_dp_ctrl_channel_eq_ok(struct msm_dp_ctrl_private *ctrl) u8 link_status[DP_LINK_STATUS_SIZE]; int num_lanes = ctrl->link->link_params.num_lanes; - msm_dp_ctrl_read_link_status(ctrl, link_status); + drm_dp_dpcd_read_link_status(ctrl->aux, link_status); return drm_dp_channel_eq_ok(link_status, num_lanes); } @@ -1860,10 +2308,10 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) break; } else if (training_step == DP_TRAINING_1) { /* link train_1 failed */ - if (!msm_dp_catalog_link_is_connected(ctrl->catalog)) + if (!msm_dp_aux_is_link_connected(ctrl->aux)) break; - msm_dp_ctrl_read_link_status(ctrl, link_status); + drm_dp_dpcd_read_link_status(ctrl->aux, link_status); rc = msm_dp_ctrl_link_rate_down_shift(ctrl); if (rc < 0) { /* already in RBR = 1.6G */ @@ -1885,10 +2333,10 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) } } else if (training_step == DP_TRAINING_2) { /* link train_2 failed */ - if (!msm_dp_catalog_link_is_connected(ctrl->catalog)) + if (!msm_dp_aux_is_link_connected(ctrl->aux)) break; - msm_dp_ctrl_read_link_status(ctrl, link_status); + drm_dp_dpcd_read_link_status(ctrl->aux, link_status); if (!drm_dp_clock_recovery_ok(link_status, ctrl->link->link_params.num_lanes)) @@ -1902,7 +2350,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) } /* stop link training before start re training */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); } rc = msm_dp_ctrl_reinitialize_mainlink(ctrl); @@ -1926,7 +2374,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) * link training failed * end txing train pattern here */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); msm_dp_ctrl_deinitialize_mainlink(ctrl); rc = -ECONNRESET; @@ -1942,6 +2390,62 @@ static int msm_dp_ctrl_link_retrain(struct msm_dp_ctrl_private *ctrl) return msm_dp_ctrl_setup_main_link(ctrl, &training_step); } +static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, + u32 rate, u32 stream_rate_khz, + bool is_ycbcr_420) +{ + u32 pixel_m, pixel_n; + u32 mvid, nvid, pixel_div = 0, dispcc_input_rate; + u32 const nvid_fixed = DP_LINK_CONSTANT_N_VALUE; + u32 const link_rate_hbr2 = 540000; + u32 const link_rate_hbr3 = 810000; + unsigned long den, num; + + if (rate == link_rate_hbr3) + pixel_div = 6; + else if (rate == 162000 || rate == 270000) + pixel_div = 2; + else if (rate == link_rate_hbr2) + pixel_div = 4; + else + DRM_ERROR("Invalid pixel mux divider\n"); + + dispcc_input_rate = (rate * 10) / pixel_div; + + rational_best_approximation(dispcc_input_rate, stream_rate_khz, + (unsigned long)(1 << 16) - 1, + (unsigned long)(1 << 16) - 1, &den, &num); + + den = ~(den - num); + den = den & 0xFFFF; + pixel_m = num; + pixel_n = den; + + mvid = (pixel_m & 0xFFFF) * 5; + nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); + + if (nvid < nvid_fixed) { + u32 temp; + + temp = (nvid_fixed / nvid) * nvid; + mvid = (nvid_fixed / nvid) * mvid; + nvid = temp; + } + + if (is_ycbcr_420) + mvid /= 2; + + if (link_rate_hbr2 == rate) + nvid *= 2; + + if (link_rate_hbr3 == rate) + nvid *= 3; + + drm_dbg_dp(ctrl->drm_dev, "mvid=0x%x, nvid=0x%x\n", mvid, nvid); + msm_dp_write_link(ctrl, REG_DP_SOFTWARE_MVID, mvid); + msm_dp_write_link(ctrl, REG_DP_SOFTWARE_NVID, nvid); +} + int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train) { int ret = 0; @@ -1997,7 +2501,7 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train msm_dp_ctrl_link_retrain(ctrl); /* stop txing train pattern to end link training */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); /* * Set up transfer unit values and set controller state to send @@ -2007,20 +2511,22 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train msm_dp_ctrl_configure_source_params(ctrl); - msm_dp_catalog_ctrl_config_msa(ctrl->catalog, + msm_dp_ctrl_config_msa(ctrl, ctrl->link->link_params.rate, pixel_rate_orig, ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420); + msm_dp_panel_clear_dsc_dto(ctrl->panel); + msm_dp_ctrl_setup_tr_unit(ctrl); - msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); ret = msm_dp_ctrl_wait4video_ready(ctrl); if (ret) return ret; - mainlink_ready = msm_dp_catalog_ctrl_mainlink_ready(ctrl->catalog); + mainlink_ready = msm_dp_ctrl_mainlink_ready(ctrl); drm_dbg_dp(ctrl->drm_dev, "mainlink %s\n", mainlink_ready ? "READY" : "NOT READY"); @@ -2036,12 +2542,12 @@ void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); phy = ctrl->phy; - msm_dp_catalog_panel_disable_vsc_sdp(ctrl->catalog); + msm_dp_panel_disable_vsc_sdp(ctrl->panel); /* set dongle to D3 (power off) mode */ msm_dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true); - msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); + msm_dp_ctrl_mainlink_disable(ctrl); if (ctrl->stream_clks_on) { clk_disable_unprepare(ctrl->pixel_clk); @@ -2069,8 +2575,9 @@ void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); phy = ctrl->phy; - msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); + msm_dp_ctrl_mainlink_disable(ctrl); + dev_pm_opp_set_rate(ctrl->dev, 0); msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); DRM_DEBUG_DP("Before, phy=%p init_count=%d power_on=%d\n", @@ -2090,11 +2597,11 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); phy = ctrl->phy; - msm_dp_catalog_panel_disable_vsc_sdp(ctrl->catalog); + msm_dp_panel_disable_vsc_sdp(ctrl->panel); - msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); + msm_dp_ctrl_mainlink_disable(ctrl); - msm_dp_catalog_ctrl_reset(ctrl->catalog); + msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl); if (ctrl->stream_clks_on) { clk_disable_unprepare(ctrl->pixel_clk); @@ -2121,7 +2628,7 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); if (ctrl->panel->psr_cap.version) { - isr = msm_dp_catalog_ctrl_read_psr_interrupt_status(ctrl->catalog); + isr = msm_dp_ctrl_get_psr_interrupt(ctrl); if (isr) complete(&ctrl->psr_op_comp); @@ -2136,8 +2643,7 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "PSR frame capture done\n"); } - isr = msm_dp_catalog_ctrl_get_interrupt(ctrl->catalog); - + isr = msm_dp_ctrl_get_interrupt(ctrl); if (isr & DP_CTRL_INTR_READY_FOR_VIDEO) { drm_dbg_dp(ctrl->drm_dev, "dp_video_ready\n"); @@ -2151,6 +2657,11 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl) ret = IRQ_HANDLED; } + /* DP aux isr */ + isr = msm_dp_ctrl_get_aux_interrupt(ctrl); + if (isr) + ret |= msm_dp_aux_isr(ctrl->aux, isr); + return ret; } @@ -2206,14 +2717,14 @@ static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl) struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, struct msm_dp_panel *panel, struct drm_dp_aux *aux, - struct msm_dp_catalog *catalog, - struct phy *phy) + struct phy *phy, + void __iomem *ahb_base, + void __iomem *link_base) { struct msm_dp_ctrl_private *ctrl; int ret; - if (!dev || !panel || !aux || - !link || !catalog) { + if (!dev || !panel || !aux || !link) { DRM_ERROR("invalid input\n"); return ERR_PTR(-EINVAL); } @@ -2244,9 +2755,10 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link ctrl->panel = panel; ctrl->aux = aux; ctrl->link = link; - ctrl->catalog = catalog; ctrl->dev = dev; ctrl->phy = phy; + ctrl->ahb_base = ahb_base; + ctrl->link_base = link_base; ret = msm_dp_ctrl_clk_init(&ctrl->msm_dp_ctrl); if (ret) { diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index b7abfedbf574..124b9b21bb7f 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -9,7 +9,6 @@ #include "dp_aux.h" #include "dp_panel.h" #include "dp_link.h" -#include "dp_catalog.h" struct msm_dp_ctrl { bool wide_bus_en; @@ -25,12 +24,15 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl); irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl); -struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, - struct msm_dp_panel *panel, struct drm_dp_aux *aux, - struct msm_dp_catalog *catalog, - struct phy *phy); - -void msm_dp_ctrl_reset_irq_ctrl(struct msm_dp_ctrl *msm_dp_ctrl, bool enable); +struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, + struct msm_dp_link *link, + struct msm_dp_panel *panel, + struct drm_dp_aux *aux, + struct phy *phy, + void __iomem *ahb_base, + void __iomem *link_base); + +void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_irq_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl); @@ -41,4 +43,7 @@ void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl); int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl); + #endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 22fd946ee201..cf3838fcd154 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -5,11 +5,12 @@ #define pr_fmt(fmt)"[drm-dp] %s: " fmt, __func__ +#ifdef CONFIG_DEBUG_FS + #include <linux/debugfs.h> #include <drm/drm_connector.h> #include <drm/drm_file.h> -#include "dp_catalog.h" #include "dp_aux.h" #include "dp_ctrl.h" #include "dp_debug.h" @@ -235,3 +236,5 @@ int msm_dp_debug_init(struct device *dev, struct msm_dp_panel *panel, return 0; } + +#endif diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index aba925aab7ad..9bd9cd5c1e03 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -11,13 +11,14 @@ #include <linux/of_irq.h> #include <linux/phy/phy.h> #include <linux/delay.h> +#include <linux/string_choices.h> #include <drm/display/drm_dp_aux_bus.h> +#include <drm/display/drm_hdmi_audio_helper.h> #include <drm/drm_edid.h> #include "msm_drv.h" #include "msm_kms.h" #include "dp_ctrl.h" -#include "dp_catalog.h" #include "dp_aux.h" #include "dp_reg.h" #include "dp_link.h" @@ -85,7 +86,6 @@ struct msm_dp_display_private { struct drm_device *drm_dev; - struct msm_dp_catalog *catalog; struct drm_dp_aux *aux; struct msm_dp_link *link; struct msm_dp_panel *panel; @@ -110,6 +110,18 @@ struct msm_dp_display_private { bool wide_bus_supported; struct msm_dp_audio *audio; + + void __iomem *ahb_base; + size_t ahb_len; + + void __iomem *aux_base; + size_t aux_len; + + void __iomem *link_base; + size_t link_len; + + void __iomem *p0_base; + size_t p0_len; }; struct msm_dp_desc { @@ -118,6 +130,14 @@ struct msm_dp_desc { bool wide_bus_supported; }; +static const struct msm_dp_desc msm_dp_desc_glymur[] = { + { .io_start = 0x0af54000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, + { .io_start = 0x0af5c000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true }, + { .io_start = 0x0af64000, .id = MSM_DP_CONTROLLER_2, .wide_bus_supported = true }, + { .io_start = 0x0af6c000, .id = MSM_DP_CONTROLLER_3, .wide_bus_supported = true }, + {} +}; + static const struct msm_dp_desc msm_dp_desc_sa8775p[] = { { .io_start = 0x0af54000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, { .io_start = 0x0af5c000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true }, @@ -126,6 +146,11 @@ static const struct msm_dp_desc msm_dp_desc_sa8775p[] = { {} }; +static const struct msm_dp_desc msm_dp_desc_sdm845[] = { + { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0 }, + {} +}; + static const struct msm_dp_desc msm_dp_desc_sc7180[] = { { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, {} @@ -170,6 +195,7 @@ static const struct msm_dp_desc msm_dp_desc_x1e80100[] = { }; static const struct of_device_id msm_dp_dt_match[] = { + { .compatible = "qcom,glymur-dp", .data = &msm_dp_desc_glymur }, { .compatible = "qcom,sa8775p-dp", .data = &msm_dp_desc_sa8775p }, { .compatible = "qcom,sc7180-dp", .data = &msm_dp_desc_sc7180 }, { .compatible = "qcom,sc7280-dp", .data = &msm_dp_desc_sc7280 }, @@ -178,7 +204,7 @@ static const struct of_device_id msm_dp_dt_match[] = { { .compatible = "qcom,sc8180x-edp", .data = &msm_dp_desc_sc8180x }, { .compatible = "qcom,sc8280xp-dp", .data = &msm_dp_desc_sc8280xp }, { .compatible = "qcom,sc8280xp-edp", .data = &msm_dp_desc_sc8280xp }, - { .compatible = "qcom,sdm845-dp", .data = &msm_dp_desc_sc7180 }, + { .compatible = "qcom,sdm845-dp", .data = &msm_dp_desc_sdm845 }, { .compatible = "qcom,sm8350-dp", .data = &msm_dp_desc_sc7180 }, { .compatible = "qcom,sm8650-dp", .data = &msm_dp_desc_sm8650 }, { .compatible = "qcom,x1e80100-dp", .data = &msm_dp_desc_x1e80100 }, @@ -275,9 +301,7 @@ static int msm_dp_display_bind(struct device *dev, struct device *master, struct drm_device *drm = priv->dev; dp->msm_dp_display.drm_dev = drm; - priv->dp[dp->id] = &dp->msm_dp_display; - - + priv->kms->dp[dp->id] = &dp->msm_dp_display; dp->drm_dev = drm; dp->aux->drm_dev = drm; @@ -287,13 +311,6 @@ static int msm_dp_display_bind(struct device *dev, struct device *master, goto end; } - - rc = msm_dp_register_audio_driver(dev, dp->audio); - if (rc) { - DRM_ERROR("Audio registration Dp failed\n"); - goto end; - } - rc = msm_dp_hpd_event_thread_start(dp); if (rc) { DRM_ERROR("Event thread create failed\n"); @@ -315,11 +332,10 @@ static void msm_dp_display_unbind(struct device *dev, struct device *master, of_dp_aux_depopulate_bus(dp->aux); - msm_dp_unregister_audio_driver(dev, dp->audio); msm_dp_aux_unregister(dp->aux); dp->drm_dev = NULL; dp->aux->drm_dev = NULL; - priv->dp[dp->id] = NULL; + priv->kms->dp[dp->id] = NULL; } static const struct component_ops msm_dp_display_comp_ops = { @@ -343,8 +359,7 @@ static int msm_dp_display_send_hpd_notification(struct msm_dp_display_private *d { if ((hpd && dp->msm_dp_display.link_ready) || (!hpd && !dp->msm_dp_display.link_ready)) { - drm_dbg_dp(dp->drm_dev, "HPD already %s\n", - (hpd ? "on" : "off")); + drm_dbg_dp(dp->drm_dev, "HPD already %s\n", str_on_off(hpd)); return 0; } @@ -367,11 +382,35 @@ static int msm_dp_display_send_hpd_notification(struct msm_dp_display_private *d return 0; } +static int msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd) +{ + int rc, lttpr_count; + + if (drm_dp_read_lttpr_common_caps(dp->aux, dpcd, dp->link->lttpr_common_caps)) + return 0; + + lttpr_count = drm_dp_lttpr_count(dp->link->lttpr_common_caps); + rc = drm_dp_lttpr_init(dp->aux, lttpr_count); + if (rc) { + DRM_ERROR("failed to set LTTPRs transparency mode, rc=%d\n", rc); + return 0; + } + + return lttpr_count; +} + static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) { struct drm_connector *connector = dp->msm_dp_display.connector; const struct drm_display_info *info = &connector->display_info; int rc = 0; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; + + rc = drm_dp_read_dpcd_caps(dp->aux, dpcd); + if (rc) + goto end; + + dp->link->lttpr_count = msm_dp_display_lttpr_init(dp, dpcd); rc = msm_dp_panel_read_sink_caps(dp->panel, connector); if (rc) @@ -440,7 +479,8 @@ static void msm_dp_display_host_init(struct msm_dp_display_private *dp) dp->phy_initialized); msm_dp_ctrl_core_clk_enable(dp->ctrl); - msm_dp_ctrl_reset_irq_ctrl(dp->ctrl, true); + msm_dp_ctrl_reset(dp->ctrl); + msm_dp_ctrl_enable_irq(dp->ctrl); msm_dp_aux_init(dp->aux); dp->core_initialized = true; } @@ -451,7 +491,8 @@ static void msm_dp_display_host_deinit(struct msm_dp_display_private *dp) dp->msm_dp_display.connector_type, dp->core_initialized, dp->phy_initialized); - msm_dp_ctrl_reset_irq_ctrl(dp->ctrl, false); + msm_dp_ctrl_reset(dp->ctrl); + msm_dp_ctrl_disable_irq(dp->ctrl); msm_dp_aux_deinit(dp->aux); msm_dp_ctrl_core_clk_disable(dp->ctrl); dp->core_initialized = false; @@ -611,9 +652,9 @@ static void msm_dp_display_handle_plugged_change(struct msm_dp *msm_dp_display, struct msm_dp_display_private, msm_dp_display); /* notify audio subsystem only if sink supports audio */ - if (msm_dp_display->plugged_cb && msm_dp_display->codec_dev && - dp->audio_supported) - msm_dp_display->plugged_cb(msm_dp_display->codec_dev, plugged); + if (dp->audio_supported) + drm_connector_hdmi_audio_plugged_notify(msm_dp_display->connector, + plugged); } static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp, u32 data) @@ -722,9 +763,6 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) { int rc = 0; struct device *dev = &dp->msm_dp_display.pdev->dev; - struct msm_dp_panel_in panel_in = { - .dev = dev, - }; struct phy *phy; phy = devm_phy_get(dev, "dp"); @@ -735,21 +773,10 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) dp->msm_dp_display.is_edp ? PHY_SUBMODE_EDP : PHY_SUBMODE_DP); if (rc) { DRM_ERROR("failed to set phy submode, rc = %d\n", rc); - dp->catalog = NULL; goto error; } - dp->catalog = msm_dp_catalog_get(dev); - if (IS_ERR(dp->catalog)) { - rc = PTR_ERR(dp->catalog); - DRM_ERROR("failed to initialize catalog, rc = %d\n", rc); - dp->catalog = NULL; - goto error; - } - - dp->aux = msm_dp_aux_get(dev, dp->catalog, - phy, - dp->msm_dp_display.is_edp); + dp->aux = msm_dp_aux_get(dev, phy, dp->msm_dp_display.is_edp, dp->aux_base); if (IS_ERR(dp->aux)) { rc = PTR_ERR(dp->aux); DRM_ERROR("failed to initialize aux, rc = %d\n", rc); @@ -765,11 +792,7 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) goto error_link; } - panel_in.aux = dp->aux; - panel_in.catalog = dp->catalog; - panel_in.link = dp->link; - - dp->panel = msm_dp_panel_get(&panel_in); + dp->panel = msm_dp_panel_get(dev, dp->aux, dp->link, dp->link_base, dp->p0_base); if (IS_ERR(dp->panel)) { rc = PTR_ERR(dp->panel); DRM_ERROR("failed to initialize panel, rc = %d\n", rc); @@ -778,8 +801,7 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) } dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, - dp->catalog, - phy); + phy, dp->ahb_base, dp->link_base); if (IS_ERR(dp->ctrl)) { rc = PTR_ERR(dp->ctrl); DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); @@ -787,7 +809,7 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) goto error_ctrl; } - dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->panel, dp->catalog); + dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->link_base); if (IS_ERR(dp->audio)) { rc = PTR_ERR(dp->audio); pr_err("failed to initialize audio, rc = %d\n", rc); @@ -899,19 +921,6 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) return 0; } -int msm_dp_display_set_plugged_cb(struct msm_dp *msm_dp_display, - hdmi_codec_plugged_cb fn, struct device *codec_dev) -{ - bool plugged; - - msm_dp_display->plugged_cb = fn; - msm_dp_display->codec_dev = codec_dev; - plugged = msm_dp_display->link_ready; - msm_dp_display_handle_plugged_change(msm_dp_display, plugged); - - return 0; -} - /** * msm_dp_bridge_mode_valid - callback to determine if specified mode is valid * @bridge: Pointer to drm bridge structure @@ -937,16 +946,17 @@ enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, return -EINVAL; } - if (mode->clock > DP_MAX_PIXEL_CLK_KHZ) - return MODE_CLOCK_HIGH; - msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); link_info = &msm_dp_display->panel->link_info; - if (drm_mode_is_420_only(&dp->connector->display_info, mode) && - msm_dp_display->panel->vsc_sdp_supported) + if ((drm_mode_is_420_only(&dp->connector->display_info, mode) && + msm_dp_display->panel->vsc_sdp_supported) || + msm_dp_wide_bus_available(dp)) mode_pclk_khz /= 2; + if (mode_pclk_khz > DP_MAX_PIXEL_CLK_KHZ) + return MODE_CLOCK_HIGH; + mode_bpp = dp->connector->display_info.bpc * num_components; if (!mode_bpp) mode_bpp = default_bpp; @@ -1022,7 +1032,14 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp) return; } - msm_dp_catalog_snapshot(msm_dp_display->catalog, disp_state); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->ahb_len, + msm_dp_display->ahb_base, "dp_ahb"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->aux_len, + msm_dp_display->aux_base, "dp_aux"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->link_len, + msm_dp_display->link_base, "dp_link"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->p0_len, + msm_dp_display->p0_base, "dp_p0"); mutex_unlock(&msm_dp_display->event_mutex); } @@ -1145,7 +1162,7 @@ static irqreturn_t msm_dp_display_irq_handler(int irq, void *dev_id) return IRQ_NONE; } - hpd_isr_status = msm_dp_catalog_hpd_get_intr_status(dp->catalog); + hpd_isr_status = msm_dp_aux_get_hpd_intr_status(dp->aux); if (hpd_isr_status & 0x0F) { drm_dbg_dp(dp->drm_dev, "type=%d isr=0x%x\n", @@ -1172,9 +1189,6 @@ static irqreturn_t msm_dp_display_irq_handler(int irq, void *dev_id) /* DP controller isr */ ret |= msm_dp_ctrl_isr(dp->ctrl); - /* DP aux isr */ - ret |= msm_dp_aux_isr(dp->aux); - return ret; } @@ -1272,6 +1286,80 @@ static int msm_dp_display_get_connector_type(struct platform_device *pdev, return connector_type; } +static void __iomem *msm_dp_ioremap(struct platform_device *pdev, int idx, size_t *len) +{ + struct resource *res; + void __iomem *base; + + base = devm_platform_get_and_ioremap_resource(pdev, idx, &res); + if (!IS_ERR(base)) + *len = resource_size(res); + + return base; +} + +#define DP_DEFAULT_AHB_OFFSET 0x0000 +#define DP_DEFAULT_AHB_SIZE 0x0200 +#define DP_DEFAULT_AUX_OFFSET 0x0200 +#define DP_DEFAULT_AUX_SIZE 0x0200 +#define DP_DEFAULT_LINK_OFFSET 0x0400 +#define DP_DEFAULT_LINK_SIZE 0x0C00 +#define DP_DEFAULT_P0_OFFSET 0x1000 +#define DP_DEFAULT_P0_SIZE 0x0400 + +static int msm_dp_display_get_io(struct msm_dp_display_private *display) +{ + struct platform_device *pdev = display->msm_dp_display.pdev; + + display->ahb_base = msm_dp_ioremap(pdev, 0, &display->ahb_len); + if (IS_ERR(display->ahb_base)) + return PTR_ERR(display->ahb_base); + + display->aux_base = msm_dp_ioremap(pdev, 1, &display->aux_len); + if (IS_ERR(display->aux_base)) { + if (display->aux_base != ERR_PTR(-EINVAL)) { + DRM_ERROR("unable to remap aux region: %pe\n", display->aux_base); + return PTR_ERR(display->aux_base); + } + + /* + * The initial binding had a single reg, but in order to + * support variation in the sub-region sizes this was split. + * msm_dp_ioremap() will fail with -EINVAL here if only a single + * reg is specified, so fill in the sub-region offsets and + * lengths based on this single region. + */ + if (display->ahb_len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) { + DRM_ERROR("legacy memory region not large enough\n"); + return -EINVAL; + } + + display->ahb_len = DP_DEFAULT_AHB_SIZE; + display->aux_base = display->ahb_base + DP_DEFAULT_AUX_OFFSET; + display->aux_len = DP_DEFAULT_AUX_SIZE; + display->link_base = display->ahb_base + DP_DEFAULT_LINK_OFFSET; + display->link_len = DP_DEFAULT_LINK_SIZE; + display->p0_base = display->ahb_base + DP_DEFAULT_P0_OFFSET; + display->p0_len = DP_DEFAULT_P0_SIZE; + + return 0; + } + + display->link_base = msm_dp_ioremap(pdev, 2, &display->link_len); + if (IS_ERR(display->link_base)) { + DRM_ERROR("unable to remap link region: %pe\n", display->link_base); + return PTR_ERR(display->link_base); + } + + display->p0_base = msm_dp_ioremap(pdev, 3, &display->p0_len); + if (IS_ERR(display->p0_base)) { + DRM_ERROR("unable to remap p0 region: %pe\n", display->p0_base); + return PTR_ERR(display->p0_base); + } + + return 0; +} + static int msm_dp_display_probe(struct platform_device *pdev) { int rc = 0; @@ -1298,6 +1386,10 @@ static int msm_dp_display_probe(struct platform_device *pdev) dp->msm_dp_display.is_edp = (dp->msm_dp_display.connector_type == DRM_MODE_CONNECTOR_eDP); + rc = msm_dp_display_get_io(dp); + if (rc) + return rc; + rc = msm_dp_init_sub_modules(dp); if (rc) { DRM_ERROR("init sub module failed\n"); @@ -1360,7 +1452,7 @@ static int msm_dp_pm_runtime_suspend(struct device *dev) if (dp->msm_dp_display.is_edp) { msm_dp_display_host_phy_exit(dp); - msm_dp_catalog_ctrl_hpd_disable(dp->catalog); + msm_dp_aux_hpd_disable(dp->aux); } msm_dp_display_host_deinit(dp); @@ -1381,7 +1473,7 @@ static int msm_dp_pm_runtime_resume(struct device *dev) */ msm_dp_display_host_init(dp); if (dp->msm_dp_display.is_edp) { - msm_dp_catalog_ctrl_hpd_enable(dp->catalog); + msm_dp_aux_hpd_enable(dp->aux); msm_dp_display_host_phy_init(dp); } @@ -1397,7 +1489,7 @@ static const struct dev_pm_ops msm_dp_pm_ops = { static struct platform_driver msm_dp_display_driver = { .probe = msm_dp_display_probe, - .remove_new = msm_dp_display_remove, + .remove = msm_dp_display_remove, .driver = { .name = "msm-dp-display", .of_match_table = msm_dp_dt_match, @@ -1498,13 +1590,13 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev, } void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); struct msm_dp *dp = msm_dp_bridge->msm_dp_display; int rc = 0; struct msm_dp_display_private *msm_dp_display; - u32 state; + u32 hpd_state; bool force_link_train = false; msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); @@ -1523,8 +1615,8 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, return; } - state = msm_dp_display->hpd_state; - if (state != ST_DISPLAY_OFF && state != ST_MAINLINK_READY) { + hpd_state = msm_dp_display->hpd_state; + if (hpd_state != ST_DISPLAY_OFF && hpd_state != ST_MAINLINK_READY) { mutex_unlock(&msm_dp_display->event_mutex); return; } @@ -1536,9 +1628,9 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, return; } - state = msm_dp_display->hpd_state; + hpd_state = msm_dp_display->hpd_state; - if (state == ST_DISPLAY_OFF) { + if (hpd_state == ST_DISPLAY_OFF) { msm_dp_display_host_phy_init(msm_dp_display); force_link_train = true; } @@ -1559,7 +1651,7 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, } void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); struct msm_dp *dp = msm_dp_bridge->msm_dp_display; @@ -1571,11 +1663,11 @@ void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, } void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); struct msm_dp *dp = msm_dp_bridge->msm_dp_display; - u32 state; + u32 hpd_state; struct msm_dp_display_private *msm_dp_display; msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); @@ -1585,15 +1677,15 @@ void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, mutex_lock(&msm_dp_display->event_mutex); - state = msm_dp_display->hpd_state; - if (state != ST_DISCONNECT_PENDING && state != ST_CONNECTED) + hpd_state = msm_dp_display->hpd_state; + if (hpd_state != ST_DISCONNECT_PENDING && hpd_state != ST_CONNECTED) drm_dbg_dp(dp->drm_dev, "type=%d wrong hpd_state=%d\n", - dp->connector_type, state); + dp->connector_type, hpd_state); msm_dp_display_disable(msm_dp_display); - state = msm_dp_display->hpd_state; - if (state == ST_DISCONNECT_PENDING) { + hpd_state = msm_dp_display->hpd_state; + if (hpd_state == ST_DISCONNECT_PENDING) { /* completed disconnection */ msm_dp_display->hpd_state = ST_DISCONNECTED; } else { @@ -1643,8 +1735,6 @@ void msm_dp_bridge_mode_set(struct drm_bridge *drm_bridge, /* populate wide_bus_support to different layers */ msm_dp_display->ctrl->wide_bus_en = msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 ? false : msm_dp_display->wide_bus_supported; - msm_dp_display->catalog->wide_bus_en = - msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 ? false : msm_dp_display->wide_bus_supported; } void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge) @@ -1668,10 +1758,8 @@ void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge) return; } - msm_dp_catalog_ctrl_hpd_enable(dp->catalog); - - /* enable HDP interrupts */ - msm_dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, true); + msm_dp_aux_hpd_enable(dp->aux); + msm_dp_aux_hpd_intr_enable(dp->aux); msm_dp_display->internal_hpd = true; mutex_unlock(&dp->event_mutex); @@ -1684,9 +1772,9 @@ void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge) struct msm_dp_display_private *dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); mutex_lock(&dp->event_mutex); - /* disable HDP interrupts */ - msm_dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, false); - msm_dp_catalog_ctrl_hpd_disable(dp->catalog); + + msm_dp_aux_hpd_intr_disable(dp->aux); + msm_dp_aux_hpd_disable(dp->aux); msm_dp_display->internal_hpd = false; diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index ecbc2d92f546..cc6e2cab36e9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -7,7 +7,6 @@ #define _DP_DISPLAY_H_ #include "dp_panel.h" -#include <sound/hdmi-codec.h> #include "disp/msm_disp_snapshot.h" #define DP_MAX_PIXEL_CLK_KHZ 675000 @@ -15,7 +14,6 @@ struct msm_dp { struct drm_device *drm_dev; struct platform_device *pdev; - struct device *codec_dev; struct drm_connector *connector; struct drm_bridge *next_bridge; bool link_ready; @@ -25,14 +23,10 @@ struct msm_dp { bool is_edp; bool internal_hpd; - hdmi_codec_plugged_cb plugged_cb; - struct msm_dp_audio *msm_dp_audio; bool psr_supported; }; -int msm_dp_display_set_plugged_cb(struct msm_dp *msm_dp_display, - hdmi_codec_plugged_cb fn, struct device *codec_dev); int msm_dp_display_get_modes(struct msm_dp *msm_dp_display); bool msm_dp_display_check_video_test(struct msm_dp *msm_dp_display); int msm_dp_display_get_test_bpp(struct msm_dp *msm_dp_display); diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index d3e241ea6941..9a461ab2f32f 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -3,6 +3,7 @@ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ +#include <linux/string_choices.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic.h> #include <drm/drm_bridge.h> @@ -11,6 +12,7 @@ #include "msm_drv.h" #include "msm_kms.h" +#include "dp_audio.h" #include "dp_drm.h" /** @@ -18,14 +20,15 @@ * @bridge: Pointer to drm bridge structure * Returns: Bridge's 'is connected' status */ -static enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge) +static enum drm_connector_status +msm_dp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector) { struct msm_dp *dp; dp = to_dp_bridge(bridge)->msm_dp_display; drm_dbg_dp(dp->drm_dev, "link_ready = %s\n", - (dp->link_ready) ? "true" : "false"); + str_true_false(dp->link_ready)); return (dp->link_ready) ? connector_status_connected : connector_status_disconnected; @@ -41,7 +44,7 @@ static int msm_dp_bridge_atomic_check(struct drm_bridge *bridge, dp = to_dp_bridge(bridge)->msm_dp_display; drm_dbg_dp(dp->drm_dev, "link_ready = %s\n", - (dp->link_ready) ? "true" : "false"); + str_true_false(dp->link_ready)); /* * There is no protection in the DRM framework to check if the display @@ -113,6 +116,9 @@ static const struct drm_bridge_funcs msm_dp_bridge_ops = { .hpd_disable = msm_dp_bridge_hpd_disable, .hpd_notify = msm_dp_bridge_hpd_notify, .debugfs_init = msm_dp_bridge_debugfs_init, + + .dp_audio_prepare = msm_dp_audio_prepare, + .dp_audio_shutdown = msm_dp_audio_shutdown, }; static int msm_edp_bridge_atomic_check(struct drm_bridge *drm_bridge, @@ -137,9 +143,8 @@ static int msm_edp_bridge_atomic_check(struct drm_bridge *drm_bridge, } static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { - struct drm_atomic_state *atomic_state = old_bridge_state->base.state; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); @@ -151,25 +156,24 @@ static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge, * If the panel is in psr, just exit psr state and skip the full * bridge enable sequence. */ - crtc = drm_atomic_get_new_crtc_for_encoder(atomic_state, + crtc = drm_atomic_get_new_crtc_for_encoder(state, drm_bridge->encoder); if (!crtc) return; - old_crtc_state = drm_atomic_get_old_crtc_state(atomic_state, crtc); + old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); if (old_crtc_state && old_crtc_state->self_refresh_active) { msm_dp_display_set_psr(dp, false); return; } - msm_dp_bridge_atomic_enable(drm_bridge, old_bridge_state); + msm_dp_bridge_atomic_enable(drm_bridge, state); } static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *atomic_state) { - struct drm_atomic_state *atomic_state = old_bridge_state->base.state; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state = NULL, *old_crtc_state = NULL; struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); @@ -208,13 +212,12 @@ static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge, } out: - msm_dp_bridge_atomic_disable(drm_bridge, old_bridge_state); + msm_dp_bridge_atomic_disable(drm_bridge, atomic_state); } static void msm_edp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *atomic_state) { - struct drm_atomic_state *atomic_state = old_bridge_state->base.state; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state = NULL; @@ -233,7 +236,7 @@ static void msm_edp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, if (new_crtc_state->self_refresh_active) return; - msm_dp_bridge_atomic_post_disable(drm_bridge, old_bridge_state); + msm_dp_bridge_atomic_post_disable(drm_bridge, atomic_state); } /** @@ -257,7 +260,10 @@ static enum drm_mode_status msm_edp_bridge_mode_valid(struct drm_bridge *bridge, return -EINVAL; } - if (mode->clock > DP_MAX_PIXEL_CLK_KHZ) + if (msm_dp_wide_bus_available(dp)) + mode_pclk_khz /= 2; + + if (mode_pclk_khz > DP_MAX_PIXEL_CLK_KHZ) return MODE_CLOCK_HIGH; /* @@ -295,14 +301,15 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, struct msm_dp_bridge *msm_dp_bridge; struct drm_bridge *bridge; - msm_dp_bridge = devm_kzalloc(dev->dev, sizeof(*msm_dp_bridge), GFP_KERNEL); - if (!msm_dp_bridge) - return -ENOMEM; + msm_dp_bridge = devm_drm_bridge_alloc(dev->dev, struct msm_dp_bridge, bridge, + msm_dp_display->is_edp ? &msm_edp_bridge_ops : + &msm_dp_bridge_ops); + if (IS_ERR(msm_dp_bridge)) + return PTR_ERR(msm_dp_bridge); msm_dp_bridge->msm_dp_display = msm_dp_display; bridge = &msm_dp_bridge->bridge; - bridge->funcs = msm_dp_display->is_edp ? &msm_edp_bridge_ops : &msm_dp_bridge_ops; bridge->type = msm_dp_display->connector_type; bridge->ycbcr_420_allowed = yuv_supported; @@ -319,9 +326,13 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, */ if (!msm_dp_display->is_edp) { bridge->ops = + DRM_BRIDGE_OP_DP_AUDIO | DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES; + bridge->hdmi_audio_dev = &msm_dp_display->pdev->dev; + bridge->hdmi_audio_max_i2s_playback_channels = 8; + bridge->hdmi_audio_dai_port = -1; } rc = devm_drm_bridge_add(dev->dev, bridge); diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index 8eae2f74839f..d8c9b905f8bf 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -26,11 +26,11 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, bool yuv_supported); void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *state); void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *state); void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *state); enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, const struct drm_display_mode *mode); diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 1a1fbb2d7d4f..34a91e194a12 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -5,12 +5,15 @@ #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ +#include <drm/drm_device.h> +#include <drm/drm_of.h> #include <drm/drm_print.h> #include "dp_reg.h" #include "dp_link.h" #include "dp_panel.h" +#define DP_LINK_RATE_HBR2 540000 /* kbytes */ #define DP_TEST_REQUEST_MASK 0x7F enum audio_sample_rate { @@ -714,21 +717,21 @@ end: static int msm_dp_link_parse_sink_status_field(struct msm_dp_link_private *link) { - int len; + int ret; link->prev_sink_count = link->msm_dp_link.sink_count; - len = drm_dp_read_sink_count(link->aux); - if (len < 0) { + ret = drm_dp_read_sink_count(link->aux); + if (ret < 0) { DRM_ERROR("DP parse sink count failed\n"); - return len; + return ret; } - link->msm_dp_link.sink_count = len; + link->msm_dp_link.sink_count = ret; - len = drm_dp_dpcd_read_link_status(link->aux, - link->link_status); - if (len < DP_LINK_STATUS_SIZE) { + ret = drm_dp_dpcd_read_link_status(link->aux, + link->link_status); + if (ret < 0) { DRM_ERROR("DP link status read failed\n"); - return len; + return ret; } return msm_dp_link_parse_request(link); @@ -1209,10 +1212,121 @@ u32 msm_dp_link_get_test_bits_depth(struct msm_dp_link *msm_dp_link, u32 bpp) return tbd; } +static u32 msm_dp_link_link_frequencies(struct device_node *of_node) +{ + struct device_node *endpoint; + u64 frequency = 0; + int cnt; + + endpoint = of_graph_get_endpoint_by_regs(of_node, 1, 0); /* port@1 */ + if (!endpoint) + return 0; + + cnt = of_property_count_u64_elems(endpoint, "link-frequencies"); + + if (cnt > 0) + of_property_read_u64_index(endpoint, "link-frequencies", + cnt - 1, &frequency); + of_node_put(endpoint); + + do_div(frequency, + 10 * /* from symbol rate to link rate */ + 1000); /* kbytes */ + + return frequency; +} + +/* + * Always populate msm_dp_link->lane_map with 4 lanes. + * - Use DTS "data-lanes" if present; otherwise fall back to default mapping. + * - For partial definitions, fill remaining entries with unused lanes in + * ascending order. + */ +static int msm_dp_link_lane_map(struct device *dev, struct msm_dp_link *msm_dp_link) +{ + struct device_node *of_node = dev->of_node; + struct device_node *endpoint; + int cnt = msm_dp_link->max_dp_lanes; + u32 tmp[DP_MAX_NUM_DP_LANES]; + u32 map[DP_MAX_NUM_DP_LANES] = {0, 1, 2, 3}; /* default 1:1 mapping */ + bool used[DP_MAX_NUM_DP_LANES] = {false}; + int i, j = 0, ret = -EINVAL; + + endpoint = of_graph_get_endpoint_by_regs(of_node, 1, -1); + if (endpoint) { + ret = of_property_read_u32_array(endpoint, "data-lanes", tmp, cnt); + if (ret) + dev_dbg(dev, "endpoint data-lanes read failed (ret=%d)\n", ret); + } + + if (ret) { + ret = of_property_read_u32_array(of_node, "data-lanes", tmp, cnt); + if (ret) { + dev_info(dev, "data-lanes not defined, set to default\n"); + goto out; + } + } + + for (i = 0; i < cnt; i++) { + if (tmp[i] >= DP_MAX_NUM_DP_LANES) { + dev_err(dev, "data-lanes[%d]=%u out of range\n", i, tmp[i]); + return -EINVAL; + } + used[tmp[i]] = true; + map[i] = tmp[i]; + } + + /* Fill the remaining entries with unused physical lanes (ascending) */ + for (i = cnt; i < DP_MAX_NUM_DP_LANES && j < DP_MAX_NUM_DP_LANES; j++) { + if (!used[j]) + map[i++] = j; + } + +out: + if (endpoint) + of_node_put(endpoint); + + dev_dbg(dev, "data-lanes count %d <%d %d %d %d>\n", cnt, map[0], map[1], map[2], map[3]); + memcpy(msm_dp_link->lane_map, map, sizeof(map)); + return 0; +} + +static int msm_dp_link_parse_dt(struct device *dev, struct msm_dp_link *msm_dp_link) +{ + struct device_node *of_node = dev->of_node; + int cnt; + + /* + * data-lanes is the property of msm_dp_out endpoint + */ + cnt = drm_of_get_data_lanes_count_ep(of_node, 1, 0, 1, DP_MAX_NUM_DP_LANES); + if (cnt < 0) { + /* legacy code, data-lanes is the property of mdss_dp node */ + cnt = drm_of_get_data_lanes_count(of_node, 1, DP_MAX_NUM_DP_LANES); + } + + if (cnt > 0) + msm_dp_link->max_dp_lanes = cnt; + else + msm_dp_link->max_dp_lanes = DP_MAX_NUM_DP_LANES; /* 4 lanes */ + + if (msm_dp_link_lane_map(dev, msm_dp_link)) { + dev_err(dev, "failed to parse data-lanes\n"); + return -EINVAL; + } + + msm_dp_link->max_dp_link_rate = msm_dp_link_link_frequencies(of_node); + if (!msm_dp_link->max_dp_link_rate) + msm_dp_link->max_dp_link_rate = DP_LINK_RATE_HBR2; + + return 0; +} + struct msm_dp_link *msm_dp_link_get(struct device *dev, struct drm_dp_aux *aux) { struct msm_dp_link_private *link; struct msm_dp_link *msm_dp_link; + int ret; if (!dev || !aux) { DRM_ERROR("invalid input\n"); @@ -1228,5 +1342,9 @@ struct msm_dp_link *msm_dp_link_get(struct device *dev, struct drm_dp_aux *aux) mutex_init(&link->psm_mutex); msm_dp_link = &link->msm_dp_link; + ret = msm_dp_link_parse_dt(dev, msm_dp_link); + if (ret) + return ERR_PTR(ret); + return msm_dp_link; } diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index 8db5d5698a97..b1eb2de6d2a7 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -7,10 +7,12 @@ #define _DP_LINK_H_ #include "dp_aux.h" +#include <drm/display/drm_dp_helper.h> #define DS_PORT_STATUS_CHANGED 0x200 #define DP_TEST_BIT_DEPTH_UNKNOWN 0xFFFFFFFF #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0) +#define DP_MAX_NUM_DP_LANES 4 struct msm_dp_link_info { unsigned char revision; @@ -60,6 +62,9 @@ struct msm_dp_link_phy_params { }; struct msm_dp_link { + u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE]; + int lttpr_count; + u32 sink_request; u32 test_response; @@ -68,6 +73,10 @@ struct msm_dp_link { struct msm_dp_link_test_audio test_audio; struct msm_dp_link_phy_params phy_params; struct msm_dp_link_info link_params; + + u32 lane_map[DP_MAX_NUM_DP_LANES]; + u32 max_dp_lanes; + u32 max_dp_link_rate; }; /** diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 5d7eaa31bf31..ad5d55bf009d 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -4,6 +4,7 @@ */ #include "dp_panel.h" +#include "dp_reg.h" #include "dp_utils.h" #include <drm/drm_connector.h> @@ -11,8 +12,9 @@ #include <drm/drm_of.h> #include <drm/drm_print.h> -#define DP_MAX_NUM_DP_LANES 4 -#define DP_LINK_RATE_HBR2 540000 /* kbytes */ +#include <linux/io.h> + +#define DP_INTF_CONFIG_DATABUS_WIDEN BIT(4) struct msm_dp_panel_private { struct device *dev; @@ -20,10 +22,46 @@ struct msm_dp_panel_private { struct msm_dp_panel msm_dp_panel; struct drm_dp_aux *aux; struct msm_dp_link *link; - struct msm_dp_catalog *catalog; + void __iomem *link_base; + void __iomem *p0_base; bool panel_on; }; +static inline u32 msm_dp_read_link(struct msm_dp_panel_private *panel, u32 offset) +{ + return readl_relaxed(panel->link_base + offset); +} + +static inline void msm_dp_write_link(struct msm_dp_panel_private *panel, + u32 offset, u32 data) +{ + /* + * To make sure link reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + writel(data, panel->link_base + offset); +} + +static inline void msm_dp_write_p0(struct msm_dp_panel_private *panel, + u32 offset, u32 data) +{ + /* + * To make sure interface reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + writel(data, panel->p0_base + offset); +} + +static inline u32 msm_dp_read_p0(struct msm_dp_panel_private *panel, + u32 offset) +{ + /* + * To make sure interface reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + return readl_relaxed(panel->p0_base + offset); +} + static void msm_dp_panel_read_psr_cap(struct msm_dp_panel_private *panel) { ssize_t rlen; @@ -47,9 +85,10 @@ static void msm_dp_panel_read_psr_cap(struct msm_dp_panel_private *panel) static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel) { - int rc; + int rc, max_lttpr_lanes, max_lttpr_rate; struct msm_dp_panel_private *panel; struct msm_dp_link_info *link_info; + struct msm_dp_link *link; u8 *dpcd, major, minor; panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); @@ -64,16 +103,30 @@ static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel) major = (link_info->revision >> 4) & 0x0f; minor = link_info->revision & 0x0f; + link = panel->link; + drm_dbg_dp(panel->drm_dev, "max_lanes=%d max_link_rate=%d\n", + link->max_dp_lanes, link->max_dp_link_rate); + 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 > msm_dp_panel->max_dp_lanes) - link_info->num_lanes = msm_dp_panel->max_dp_lanes; + if (link_info->num_lanes > link->max_dp_lanes) + link_info->num_lanes = link->max_dp_lanes; /* Limit link rate from link-frequencies of endpoint property of dtsi */ - if (link_info->rate > msm_dp_panel->max_dp_link_rate) - link_info->rate = msm_dp_panel->max_dp_link_rate; + if (link_info->rate > link->max_dp_link_rate) + link_info->rate = link->max_dp_link_rate; + + /* Limit data lanes from LTTPR capabilities, if any */ + max_lttpr_lanes = drm_dp_lttpr_max_lane_count(panel->link->lttpr_common_caps); + if (max_lttpr_lanes && max_lttpr_lanes < link_info->num_lanes) + link_info->num_lanes = max_lttpr_lanes; + + /* Limit link rate from LTTPR capabilities, if any */ + max_lttpr_rate = drm_dp_lttpr_max_link_rate(panel->link->lttpr_common_caps); + if (max_lttpr_rate && max_lttpr_rate < link_info->rate) + link_info->rate = max_lttpr_rate; drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor); drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate); @@ -122,9 +175,6 @@ int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); - drm_dbg_dp(panel->drm_dev, "max_lanes=%d max_link_rate=%d\n", - msm_dp_panel->max_dp_lanes, msm_dp_panel->max_dp_link_rate); - rc = msm_dp_panel_read_dpcd(msm_dp_panel); if (rc) { DRM_ERROR("read dpcd failed %d\n", rc); @@ -162,7 +212,7 @@ int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, if (!msm_dp_panel->drm_edid) { DRM_ERROR("panel edid read failed\n"); /* check edid read fail is due to unplug */ - if (!msm_dp_catalog_link_is_connected(panel->catalog)) { + if (!msm_dp_aux_is_link_connected(panel->aux)) { rc = -ETIMEDOUT; goto end; } @@ -242,9 +292,85 @@ void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel) } } +static void msm_dp_panel_tpg_enable(struct msm_dp_panel *msm_dp_panel, + struct drm_display_mode *drm_mode) +{ + struct msm_dp_panel_private *panel = + container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); + u32 hsync_period, vsync_period; + u32 display_v_start, display_v_end; + u32 hsync_start_x, hsync_end_x; + u32 v_sync_width; + u32 hsync_ctl; + u32 display_hctl; + + /* TPG config parameters*/ + hsync_period = drm_mode->htotal; + vsync_period = drm_mode->vtotal; + + display_v_start = ((drm_mode->vtotal - drm_mode->vsync_start) * + hsync_period); + display_v_end = ((vsync_period - (drm_mode->vsync_start - + drm_mode->vdisplay)) + * hsync_period) - 1; + + display_v_start += drm_mode->htotal - drm_mode->hsync_start; + display_v_end -= (drm_mode->hsync_start - drm_mode->hdisplay); + + hsync_start_x = drm_mode->htotal - drm_mode->hsync_start; + hsync_end_x = hsync_period - (drm_mode->hsync_start - + drm_mode->hdisplay) - 1; + + v_sync_width = drm_mode->vsync_end - drm_mode->vsync_start; + + hsync_ctl = (hsync_period << 16) | + (drm_mode->hsync_end - drm_mode->hsync_start); + display_hctl = (hsync_end_x << 16) | hsync_start_x; + + + msm_dp_write_p0(panel, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl); + msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period * + hsync_period); + msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width * + hsync_period); + msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0); + msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0); + msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl); + msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_HCTL, 0); + msm_dp_write_p0(panel, MMSS_INTF_DISPLAY_V_START_F0, display_v_start); + msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end); + msm_dp_write_p0(panel, MMSS_INTF_DISPLAY_V_START_F1, 0); + msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_V_END_F1, 0); + msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_START_F0, 0); + msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_END_F0, 0); + msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_START_F1, 0); + msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_END_F1, 0); + msm_dp_write_p0(panel, MMSS_DP_INTF_POLARITY_CTL, 0); + + msm_dp_write_p0(panel, MMSS_DP_TPG_MAIN_CONTROL, + DP_TPG_CHECKERED_RECT_PATTERN); + msm_dp_write_p0(panel, MMSS_DP_TPG_VIDEO_CONFIG, + DP_TPG_VIDEO_CONFIG_BPP_8BIT | + DP_TPG_VIDEO_CONFIG_RGB); + msm_dp_write_p0(panel, MMSS_DP_BIST_ENABLE, + DP_BIST_ENABLE_DPBIST_EN); + msm_dp_write_p0(panel, MMSS_DP_TIMING_ENGINE_EN, + DP_TIMING_ENGINE_EN_EN); + drm_dbg_dp(panel->drm_dev, "%s: enabled tpg\n", __func__); +} + +static void msm_dp_panel_tpg_disable(struct msm_dp_panel *msm_dp_panel) +{ + struct msm_dp_panel_private *panel = + container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); + + msm_dp_write_p0(panel, MMSS_DP_TPG_MAIN_CONTROL, 0x0); + msm_dp_write_p0(panel, MMSS_DP_BIST_ENABLE, 0x0); + msm_dp_write_p0(panel, MMSS_DP_TIMING_ENGINE_EN, 0x0); +} + void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable) { - struct msm_dp_catalog *catalog; struct msm_dp_panel_private *panel; if (!msm_dp_panel) { @@ -253,7 +379,6 @@ void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable) } panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); - catalog = panel->catalog; if (!panel->panel_on) { drm_dbg_dp(panel->drm_dev, @@ -262,18 +387,109 @@ void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable) } if (!enable) { - msm_dp_catalog_panel_tpg_disable(catalog); + msm_dp_panel_tpg_disable(msm_dp_panel); return; } - drm_dbg_dp(panel->drm_dev, "calling catalog tpg_enable\n"); - msm_dp_catalog_panel_tpg_enable(catalog, &panel->msm_dp_panel.msm_dp_mode.drm_mode); + drm_dbg_dp(panel->drm_dev, "calling panel's tpg_enable\n"); + msm_dp_panel_tpg_enable(msm_dp_panel, &panel->msm_dp_panel.msm_dp_mode.drm_mode); +} + +void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel *msm_dp_panel) +{ + struct msm_dp_panel_private *panel = + container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); + + msm_dp_write_p0(panel, MMSS_DP_DSC_DTO, 0x0); +} + +static void msm_dp_panel_send_vsc_sdp(struct msm_dp_panel_private *panel, struct dp_sdp *vsc_sdp) +{ + u32 header[2]; + u32 val; + int i; + + msm_dp_utils_pack_sdp_header(&vsc_sdp->sdp_header, header); + + msm_dp_write_link(panel, MMSS_DP_GENERIC0_0, header[0]); + msm_dp_write_link(panel, MMSS_DP_GENERIC0_1, header[1]); + + for (i = 0; i < sizeof(vsc_sdp->db); i += 4) { + val = ((vsc_sdp->db[i]) | (vsc_sdp->db[i + 1] << 8) | (vsc_sdp->db[i + 2] << 16) | + (vsc_sdp->db[i + 3] << 24)); + msm_dp_write_link(panel, MMSS_DP_GENERIC0_2 + i, val); + } +} + +static void msm_dp_panel_update_sdp(struct msm_dp_panel_private *panel) +{ + u32 hw_revision = panel->msm_dp_panel.hw_revision; + + if (hw_revision >= DP_HW_VERSION_1_0 && + hw_revision < DP_HW_VERSION_1_2) { + msm_dp_write_link(panel, MMSS_DP_SDP_CFG3, UPDATE_SDP); + msm_dp_write_link(panel, MMSS_DP_SDP_CFG3, 0x0); + } +} + +void msm_dp_panel_enable_vsc_sdp(struct msm_dp_panel *msm_dp_panel, struct dp_sdp *vsc_sdp) +{ + struct msm_dp_panel_private *panel = + container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); + u32 cfg, cfg2, misc; + + cfg = msm_dp_read_link(panel, MMSS_DP_SDP_CFG); + cfg2 = msm_dp_read_link(panel, MMSS_DP_SDP_CFG2); + misc = msm_dp_read_link(panel, REG_DP_MISC1_MISC0); + + cfg |= GEN0_SDP_EN; + msm_dp_write_link(panel, MMSS_DP_SDP_CFG, cfg); + + cfg2 |= GENERIC0_SDPSIZE_VALID; + msm_dp_write_link(panel, MMSS_DP_SDP_CFG2, cfg2); + + msm_dp_panel_send_vsc_sdp(panel, vsc_sdp); + + /* indicates presence of VSC (BIT(6) of MISC1) */ + misc |= DP_MISC1_VSC_SDP; + + drm_dbg_dp(panel->drm_dev, "vsc sdp enable=1\n"); + + pr_debug("misc settings = 0x%x\n", misc); + msm_dp_write_link(panel, REG_DP_MISC1_MISC0, misc); + + msm_dp_panel_update_sdp(panel); +} + +void msm_dp_panel_disable_vsc_sdp(struct msm_dp_panel *msm_dp_panel) +{ + struct msm_dp_panel_private *panel = + container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); + u32 cfg, cfg2, misc; + + cfg = msm_dp_read_link(panel, MMSS_DP_SDP_CFG); + cfg2 = msm_dp_read_link(panel, MMSS_DP_SDP_CFG2); + misc = msm_dp_read_link(panel, REG_DP_MISC1_MISC0); + + cfg &= ~GEN0_SDP_EN; + msm_dp_write_link(panel, MMSS_DP_SDP_CFG, cfg); + + cfg2 &= ~GENERIC0_SDPSIZE_VALID; + msm_dp_write_link(panel, MMSS_DP_SDP_CFG2, cfg2); + + /* switch back to MSA */ + misc &= ~DP_MISC1_VSC_SDP; + + drm_dbg_dp(panel->drm_dev, "vsc sdp enable=0\n"); + + pr_debug("misc settings = 0x%x\n", misc); + msm_dp_write_link(panel, REG_DP_MISC1_MISC0, misc); + + msm_dp_panel_update_sdp(panel); } static int msm_dp_panel_setup_vsc_sdp_yuv_420(struct msm_dp_panel *msm_dp_panel) { - struct msm_dp_catalog *catalog; - struct msm_dp_panel_private *panel; struct msm_dp_display_mode *msm_dp_mode; struct drm_dp_vsc_sdp vsc_sdp_data; struct dp_sdp vsc_sdp; @@ -284,8 +500,6 @@ static int msm_dp_panel_setup_vsc_sdp_yuv_420(struct msm_dp_panel *msm_dp_panel) return -EINVAL; } - panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); - catalog = panel->catalog; msm_dp_mode = &msm_dp_panel->msm_dp_mode; memset(&vsc_sdp_data, 0, sizeof(vsc_sdp_data)); @@ -312,35 +526,23 @@ static int msm_dp_panel_setup_vsc_sdp_yuv_420(struct msm_dp_panel *msm_dp_panel) return len; } - msm_dp_catalog_panel_enable_vsc_sdp(catalog, &vsc_sdp); + msm_dp_panel_enable_vsc_sdp(msm_dp_panel, &vsc_sdp); return 0; } -void msm_dp_panel_dump_regs(struct msm_dp_panel *msm_dp_panel) -{ - struct msm_dp_catalog *catalog; - struct msm_dp_panel_private *panel; - - panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); - catalog = panel->catalog; - - msm_dp_catalog_dump_regs(catalog); -} - -int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel) +int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en) { u32 data, total_ver, total_hor; - struct msm_dp_catalog *catalog; struct msm_dp_panel_private *panel; struct drm_display_mode *drm_mode; u32 width_blanking; u32 sync_start; u32 msm_dp_active; u32 total; + u32 reg; panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); - catalog = panel->catalog; drm_mode = &panel->msm_dp_panel.msm_dp_mode.drm_mode; drm_dbg_dp(panel->drm_dev, "width=%d hporch= %d %d %d\n", @@ -383,7 +585,20 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel) msm_dp_active = data; - msm_dp_catalog_panel_timing_cfg(catalog, total, sync_start, width_blanking, msm_dp_active); + msm_dp_write_link(panel, REG_DP_TOTAL_HOR_VER, total); + msm_dp_write_link(panel, REG_DP_START_HOR_VER_FROM_SYNC, sync_start); + msm_dp_write_link(panel, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, width_blanking); + msm_dp_write_link(panel, REG_DP_ACTIVE_HOR_VER, msm_dp_active); + + reg = msm_dp_read_p0(panel, MMSS_DP_INTF_CONFIG); + if (wide_bus_en) + reg |= DP_INTF_CONFIG_DATABUS_WIDEN; + else + reg &= ~DP_INTF_CONFIG_DATABUS_WIDEN; + + drm_dbg_dp(panel->drm_dev, "wide_bus_en=%d reg=%#x\n", wide_bus_en, reg); + + msm_dp_write_p0(panel, MMSS_DP_INTF_CONFIG, reg); if (msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420) msm_dp_panel_setup_vsc_sdp_yuv_420(msm_dp_panel); @@ -432,87 +647,32 @@ int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel) return 0; } -static u32 msm_dp_panel_link_frequencies(struct device_node *of_node) -{ - struct device_node *endpoint; - u64 frequency = 0; - int cnt; - - endpoint = of_graph_get_endpoint_by_regs(of_node, 1, 0); /* port@1 */ - if (!endpoint) - return 0; - - cnt = of_property_count_u64_elems(endpoint, "link-frequencies"); - - if (cnt > 0) - of_property_read_u64_index(endpoint, "link-frequencies", - cnt - 1, &frequency); - of_node_put(endpoint); - - do_div(frequency, - 10 * /* from symbol rate to link rate */ - 1000); /* kbytes */ - - return frequency; -} - -static int msm_dp_panel_parse_dt(struct msm_dp_panel *msm_dp_panel) -{ - struct msm_dp_panel_private *panel; - struct device_node *of_node; - int cnt; - - panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); - of_node = panel->dev->of_node; - - /* - * data-lanes is the property of msm_dp_out endpoint - */ - cnt = drm_of_get_data_lanes_count_ep(of_node, 1, 0, 1, DP_MAX_NUM_DP_LANES); - if (cnt < 0) { - /* legacy code, data-lanes is the property of mdss_dp node */ - cnt = drm_of_get_data_lanes_count(of_node, 1, DP_MAX_NUM_DP_LANES); - } - - if (cnt > 0) - msm_dp_panel->max_dp_lanes = cnt; - else - msm_dp_panel->max_dp_lanes = DP_MAX_NUM_DP_LANES; /* 4 lanes */ - - msm_dp_panel->max_dp_link_rate = msm_dp_panel_link_frequencies(of_node); - if (!msm_dp_panel->max_dp_link_rate) - msm_dp_panel->max_dp_link_rate = DP_LINK_RATE_HBR2; - - return 0; -} - -struct msm_dp_panel *msm_dp_panel_get(struct msm_dp_panel_in *in) +struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux, + struct msm_dp_link *link, + void __iomem *link_base, + void __iomem *p0_base) { struct msm_dp_panel_private *panel; struct msm_dp_panel *msm_dp_panel; - int ret; - if (!in->dev || !in->catalog || !in->aux || !in->link) { + if (!dev || !aux || !link) { DRM_ERROR("invalid input\n"); return ERR_PTR(-EINVAL); } - panel = devm_kzalloc(in->dev, sizeof(*panel), GFP_KERNEL); + panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); if (!panel) return ERR_PTR(-ENOMEM); - panel->dev = in->dev; - panel->aux = in->aux; - panel->catalog = in->catalog; - panel->link = in->link; + panel->dev = dev; + panel->aux = aux; + panel->link = link; + panel->link_base = link_base; + panel->p0_base = p0_base; msm_dp_panel = &panel->msm_dp_panel; msm_dp_panel->max_bw_code = DP_LINK_BW_8_1; - ret = msm_dp_panel_parse_dt(msm_dp_panel); - if (ret) - return ERR_PTR(ret); - return msm_dp_panel; } diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 0e944db3adf2..921a296852d4 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -6,6 +6,7 @@ #ifndef _DP_PANEL_H_ #define _DP_PANEL_H_ +#include <drm/drm_modes.h> #include <drm/msm_drm.h> #include "dp_aux.h" @@ -21,13 +22,6 @@ struct msm_dp_display_mode { bool out_fmt_is_yuv_420; }; -struct msm_dp_panel_in { - struct device *dev; - struct drm_dp_aux *aux; - struct msm_dp_link *link; - struct msm_dp_catalog *catalog; -}; - struct msm_dp_panel_psr { u8 version; u8 capabilities; @@ -45,17 +39,14 @@ struct msm_dp_panel { struct msm_dp_panel_psr psr_cap; bool video_test; bool vsc_sdp_supported; - - u32 max_dp_lanes; - u32 max_dp_link_rate; + u32 hw_revision; u32 max_bw_code; }; int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel); int msm_dp_panel_deinit(struct msm_dp_panel *msm_dp_panel); -int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel); -void msm_dp_panel_dump_regs(struct msm_dp_panel *msm_dp_panel); +int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en); int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, struct drm_connector *connector); u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_max_bpp, @@ -65,6 +56,11 @@ int msm_dp_panel_get_modes(struct msm_dp_panel *msm_dp_panel, void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel); void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable); +void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel *msm_dp_panel); + +void msm_dp_panel_enable_vsc_sdp(struct msm_dp_panel *msm_dp_panel, struct dp_sdp *vsc_sdp); +void msm_dp_panel_disable_vsc_sdp(struct msm_dp_panel *msm_dp_panel); + /** * is_link_rate_valid() - validates the link rate * @lane_rate: link rate requested by the sink @@ -92,6 +88,9 @@ static inline bool is_lane_count_valid(u32 lane_count) lane_count == 4); } -struct msm_dp_panel *msm_dp_panel_get(struct msm_dp_panel_in *in); +struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux, + struct msm_dp_link *link, + void __iomem *link_base, + void __iomem *p0_base); void msm_dp_panel_put(struct msm_dp_panel *msm_dp_panel); #endif /* _DP_PANEL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index 3835c7f5cb98..7c44d4e2cf13 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -11,6 +11,8 @@ /* DP_TX Registers */ #define REG_DP_HW_VERSION (0x00000000) +#define DP_HW_VERSION_1_0 0x10000000 +#define DP_HW_VERSION_1_2 0x10020000 #define REG_DP_SW_RESET (0x00000010) #define DP_SW_RESET (0x00000001) @@ -21,8 +23,25 @@ #define REG_DP_CLK_CTRL (0x00000018) #define REG_DP_CLK_ACTIVE (0x0000001C) + #define REG_DP_INTR_STATUS (0x00000020) +#define DP_INTR_HPD BIT(0) +#define DP_INTR_AUX_XFER_DONE BIT(3) +#define DP_INTR_WRONG_ADDR BIT(6) +#define DP_INTR_TIMEOUT BIT(9) +#define DP_INTR_NACK_DEFER BIT(12) +#define DP_INTR_WRONG_DATA_CNT BIT(15) +#define DP_INTR_I2C_NACK BIT(18) +#define DP_INTR_I2C_DEFER BIT(21) +#define DP_INTR_PLL_UNLOCKED BIT(24) +#define DP_INTR_AUX_ERROR BIT(27) + #define REG_DP_INTR_STATUS2 (0x00000024) +#define DP_INTR_READY_FOR_VIDEO BIT(0) +#define DP_INTR_IDLE_PATTERN_SENT BIT(3) +#define DP_INTR_FRAME_END BIT(6) +#define DP_INTR_CRC_UPDATED BIT(9) + #define REG_DP_INTR_STATUS3 (0x00000028) #define REG_DP_INTR_STATUS4 (0x0000002C) diff --git a/drivers/gpu/drm/msm/dp/dp_utils.c b/drivers/gpu/drm/msm/dp/dp_utils.c index 2a40f07fe2d5..4a5ebb0c33b8 100644 --- a/drivers/gpu/drm/msm/dp/dp_utils.c +++ b/drivers/gpu/drm/msm/dp/dp_utils.c @@ -74,14 +74,8 @@ u8 msm_dp_utils_calculate_parity(u32 data) return parity_byte; } -ssize_t msm_dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 *header_buff) +void msm_dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 header_buff[2]) { - size_t length; - - length = sizeof(header_buff); - if (length < DP_SDP_HEADER_SIZE) - return -ENOSPC; - header_buff[0] = FIELD_PREP(HEADER_0_MASK, sdp_header->HB0) | FIELD_PREP(PARITY_0_MASK, msm_dp_utils_calculate_parity(sdp_header->HB0)) | FIELD_PREP(HEADER_1_MASK, sdp_header->HB1) | @@ -91,6 +85,4 @@ ssize_t msm_dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 *head FIELD_PREP(PARITY_2_MASK, msm_dp_utils_calculate_parity(sdp_header->HB2)) | FIELD_PREP(HEADER_3_MASK, sdp_header->HB3) | FIELD_PREP(PARITY_3_MASK, msm_dp_utils_calculate_parity(sdp_header->HB3)); - - return length; } diff --git a/drivers/gpu/drm/msm/dp/dp_utils.h b/drivers/gpu/drm/msm/dp/dp_utils.h index 88d53157f5b5..2e4f98a863c4 100644 --- a/drivers/gpu/drm/msm/dp/dp_utils.h +++ b/drivers/gpu/drm/msm/dp/dp_utils.h @@ -31,6 +31,6 @@ u8 msm_dp_utils_get_g0_value(u8 data); u8 msm_dp_utils_get_g1_value(u8 data); u8 msm_dp_utils_calculate_parity(u32 data); -ssize_t msm_dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 *header_buff); +void msm_dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 header_buff[2]); #endif /* _DP_UTILS_H_ */ diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index efd7c23b662f..d8bb40ef820e 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -136,7 +136,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) msm_dsi->next_bridge = ext_bridge; } - priv->dsi[msm_dsi->id] = msm_dsi; + priv->kms->dsi[msm_dsi->id] = msm_dsi; return 0; } @@ -148,7 +148,7 @@ static void dsi_unbind(struct device *dev, struct device *master, struct msm_dsi *msm_dsi = dev_get_drvdata(dev); msm_dsi_tx_buf_free(msm_dsi->host); - priv->dsi[msm_dsi->id] = NULL; + priv->kms->dsi[msm_dsi->id] = NULL; } static const struct component_ops dsi_ops = { @@ -207,7 +207,7 @@ static const struct dev_pm_ops dsi_pm_ops = { static struct platform_driver dsi_driver = { .probe = dsi_dev_probe, - .remove_new = dsi_dev_remove, + .remove = dsi_dev_remove, .driver = { .name = "msm_dsi", .of_match_table = dt_match, diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 87496db203d6..93c028a122f3 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -98,6 +98,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi); int msm_dsi_runtime_suspend(struct device *dev); int msm_dsi_runtime_resume(struct device *dev); int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host); +int dsi_link_clk_set_rate_6g_v2_9(struct msm_dsi_host *msm_host); int dsi_link_clk_set_rate_v2(struct msm_dsi_host *msm_host); int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host); int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host); @@ -115,6 +116,7 @@ int dsi_dma_base_get_6g(struct msm_dsi_host *msm_host, uint64_t *iova); int dsi_dma_base_get_v2(struct msm_dsi_host *msm_host, uint64_t *iova); int dsi_clk_init_v2(struct msm_dsi_host *msm_host); int dsi_clk_init_6g_v2(struct msm_dsi_host *msm_host); +int dsi_clk_init_6g_v2_9(struct msm_dsi_host *msm_host); int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi); 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); diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 10ba7d153d1c..fed8e9b67011 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -221,6 +221,22 @@ static const struct msm_dsi_config sc7280_dsi_cfg = { }, }; +static const struct regulator_bulk_data sa8775p_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 8300 }, /* 1.2 V */ + { .supply = "refgen" }, +}; + +static const struct msm_dsi_config sa8775p_dsi_cfg = { + .io_offset = DSI_6G_REG_SHIFT, + .regulator_data = sa8775p_dsi_regulators, + .num_regulators = ARRAY_SIZE(sa8775p_dsi_regulators), + .bus_clk_names = dsi_v2_4_clk_names, + .num_bus_clks = ARRAY_SIZE(dsi_v2_4_clk_names), + .io_start = { + { 0xae94000, 0xae96000 }, + }, +}; + static const struct msm_dsi_host_cfg_ops msm_dsi_v2_host_ops = { .link_clk_set_rate = dsi_link_clk_set_rate_v2, .link_clk_enable = dsi_link_clk_enable_v2, @@ -257,6 +273,18 @@ static const struct msm_dsi_host_cfg_ops msm_dsi_6g_v2_host_ops = { .calc_clk_rate = dsi_calc_clk_rate_6g, }; +static const struct msm_dsi_host_cfg_ops msm_dsi_6g_v2_9_host_ops = { + .link_clk_set_rate = dsi_link_clk_set_rate_6g_v2_9, + .link_clk_enable = dsi_link_clk_enable_6g, + .link_clk_disable = dsi_link_clk_disable_6g, + .clk_init_ver = dsi_clk_init_6g_v2_9, + .tx_buf_alloc = dsi_tx_buf_alloc_6g, + .tx_buf_get = dsi_tx_buf_get_6g, + .tx_buf_put = dsi_tx_buf_put_6g, + .dma_base_get = dsi_dma_base_get_6g, + .calc_clk_rate = dsi_calc_clk_rate_6g, +}; + static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = { {MSM_DSI_VER_MAJOR_V2, MSM_DSI_V2_VER_MINOR_8064, &apq8064_dsi_cfg, &msm_dsi_v2_host_ops}, @@ -286,18 +314,24 @@ static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = { &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_3_0, &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, + {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_3_1, + &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_4_0, &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_4_1, &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_5_0, &sc7280_dsi_cfg, &msm_dsi_6g_v2_host_ops}, + {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_5_1, + &sa8775p_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_6_0, &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_7_0, &sm8550_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_8_0, &sm8650_dsi_cfg, &msm_dsi_6g_v2_host_ops}, + {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_9_0, + &sm8650_dsi_cfg, &msm_dsi_6g_v2_9_host_ops}, }; const struct msm_dsi_cfg_handler *msm_dsi_cfg_get(u32 major, u32 minor) diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h index 4c9b4b37681b..38f303f2ed04 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h @@ -23,12 +23,15 @@ #define MSM_DSI_6G_VER_MINOR_V2_2_0 0x20000000 #define MSM_DSI_6G_VER_MINOR_V2_2_1 0x20020001 #define MSM_DSI_6G_VER_MINOR_V2_3_0 0x20030000 +#define MSM_DSI_6G_VER_MINOR_V2_3_1 0x20030001 #define MSM_DSI_6G_VER_MINOR_V2_4_0 0x20040000 #define MSM_DSI_6G_VER_MINOR_V2_4_1 0x20040001 #define MSM_DSI_6G_VER_MINOR_V2_5_0 0x20050000 +#define MSM_DSI_6G_VER_MINOR_V2_5_1 0x20050001 #define MSM_DSI_6G_VER_MINOR_V2_6_0 0x20060000 #define MSM_DSI_6G_VER_MINOR_V2_7_0 0x20070000 #define MSM_DSI_6G_VER_MINOR_V2_8_0 0x20080000 +#define MSM_DSI_6G_VER_MINOR_V2_9_0 0x20090000 #define MSM_DSI_V2_VER_MINOR_8064 0x0 diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index a98d24b7cb00..e0de545d4077 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -119,6 +119,15 @@ struct msm_dsi_host { struct clk *pixel_clk; struct clk *byte_intf_clk; + /* + * Clocks which needs to be properly parented between DISPCC and DSI PHY + * PLL: + */ + struct clk *byte_src_clk; + struct clk *pixel_src_clk; + struct clk *dsi_pll_byte_clk; + struct clk *dsi_pll_pixel_clk; + unsigned long byte_clk_rate; unsigned long byte_intf_clk_rate; unsigned long pixel_clk_rate; @@ -143,7 +152,7 @@ struct msm_dsi_host { /* DSI 6G TX buffer*/ struct drm_gem_object *tx_gem_obj; - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; /* DSI v2 TX buffer */ void *tx_buf; @@ -179,18 +188,18 @@ struct msm_dsi_host { int irq; }; - static inline u32 dsi_read(struct msm_dsi_host *msm_host, u32 reg) { return readl(msm_host->ctrl_base + reg); } + static inline void dsi_write(struct msm_dsi_host *msm_host, u32 reg, u32 data) { writel(data, msm_host->ctrl_base + reg); } -static const struct msm_dsi_cfg_handler *dsi_get_config( - struct msm_dsi_host *msm_host) +static const struct msm_dsi_cfg_handler * +dsi_get_config(struct msm_dsi_host *msm_host) { const struct msm_dsi_cfg_handler *cfg_hnd = NULL; struct device *dev = &msm_host->pdev->dev; @@ -200,7 +209,8 @@ static const struct msm_dsi_cfg_handler *dsi_get_config( ahb_clk = msm_clk_get(msm_host->pdev, "iface"); if (IS_ERR(ahb_clk)) { - pr_err("%s: cannot get interface clock\n", __func__); + dev_err_probe(dev, PTR_ERR(ahb_clk), "%s: cannot get interface clock\n", + __func__); goto exit; } @@ -208,13 +218,13 @@ static const struct msm_dsi_cfg_handler *dsi_get_config( ret = clk_prepare_enable(ahb_clk); if (ret) { - pr_err("%s: unable to enable ahb_clk\n", __func__); + dev_err_probe(dev, ret, "%s: unable to enable ahb_clk\n", __func__); goto runtime_put; } ret = dsi_get_version(msm_host->ctrl_base, &major, &minor); if (ret) { - pr_err("%s: Invalid version\n", __func__); + dev_err_probe(dev, ret, "%s: Invalid version\n", __func__); goto disable_clks; } @@ -268,6 +278,38 @@ int dsi_clk_init_6g_v2(struct msm_dsi_host *msm_host) return ret; } +int dsi_clk_init_6g_v2_9(struct msm_dsi_host *msm_host) +{ + struct device *dev = &msm_host->pdev->dev; + int ret; + + ret = dsi_clk_init_6g_v2(msm_host); + if (ret) + return ret; + + msm_host->byte_src_clk = devm_clk_get(dev, "byte_src"); + if (IS_ERR(msm_host->byte_src_clk)) + return dev_err_probe(dev, PTR_ERR(msm_host->byte_src_clk), + "can't get byte_src clock\n"); + + msm_host->dsi_pll_byte_clk = devm_clk_get(dev, "dsi_pll_byte"); + if (IS_ERR(msm_host->dsi_pll_byte_clk)) + return dev_err_probe(dev, PTR_ERR(msm_host->dsi_pll_byte_clk), + "can't get dsi_pll_byte clock\n"); + + msm_host->pixel_src_clk = devm_clk_get(dev, "pixel_src"); + if (IS_ERR(msm_host->pixel_src_clk)) + return dev_err_probe(dev, PTR_ERR(msm_host->pixel_src_clk), + "can't get pixel_src clock\n"); + + msm_host->dsi_pll_pixel_clk = devm_clk_get(dev, "dsi_pll_pixel"); + if (IS_ERR(msm_host->dsi_pll_pixel_clk)) + return dev_err_probe(dev, PTR_ERR(msm_host->dsi_pll_pixel_clk), + "can't get dsi_pll_pixel clock\n"); + + return 0; +} + static int dsi_clk_init(struct msm_dsi_host *msm_host) { struct platform_device *pdev = msm_host->pdev; @@ -281,42 +323,31 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host) msm_host->num_bus_clks = cfg->num_bus_clks; ret = devm_clk_bulk_get(&pdev->dev, msm_host->num_bus_clks, msm_host->bus_clks); - if (ret < 0) { - dev_err(&pdev->dev, "Unable to get clocks, ret = %d\n", ret); - goto exit; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "Unable to get clocks\n"); /* get link and source clocks */ msm_host->byte_clk = msm_clk_get(pdev, "byte"); - if (IS_ERR(msm_host->byte_clk)) { - ret = PTR_ERR(msm_host->byte_clk); - pr_err("%s: can't find dsi_byte clock. ret=%d\n", - __func__, ret); - msm_host->byte_clk = NULL; - goto exit; - } + if (IS_ERR(msm_host->byte_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(msm_host->byte_clk), + "%s: can't find dsi_byte clock\n", + __func__); msm_host->pixel_clk = msm_clk_get(pdev, "pixel"); - if (IS_ERR(msm_host->pixel_clk)) { - ret = PTR_ERR(msm_host->pixel_clk); - pr_err("%s: can't find dsi_pixel clock. ret=%d\n", - __func__, ret); - msm_host->pixel_clk = NULL; - goto exit; - } + if (IS_ERR(msm_host->pixel_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(msm_host->pixel_clk), + "%s: can't find dsi_pixel clock\n", + __func__); msm_host->esc_clk = msm_clk_get(pdev, "core"); - if (IS_ERR(msm_host->esc_clk)) { - ret = PTR_ERR(msm_host->esc_clk); - pr_err("%s: can't find dsi_esc clock. ret=%d\n", - __func__, ret); - msm_host->esc_clk = NULL; - goto exit; - } + if (IS_ERR(msm_host->esc_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(msm_host->esc_clk), + "%s: can't find dsi_esc clock\n", + __func__); if (cfg_hnd->ops->clk_init_ver) ret = cfg_hnd->ops->clk_init_ver(msm_host); -exit: + return ret; } @@ -380,6 +411,25 @@ int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) return 0; } +int dsi_link_clk_set_rate_6g_v2_9(struct msm_dsi_host *msm_host) +{ + struct device *dev = &msm_host->pdev->dev; + int ret; + + /* + * DSI PHY PLLs have to be enabled to allow reparenting to them, so + * cannot use assigned-clock-parents. + */ + ret = clk_set_parent(msm_host->byte_src_clk, msm_host->dsi_pll_byte_clk); + if (ret) + dev_err(dev, "Failed to parent byte_src -> dsi_pll_byte: %d\n", ret); + + ret = clk_set_parent(msm_host->pixel_src_clk, msm_host->dsi_pll_pixel_clk); + if (ret) + dev_err(dev, "Failed to parent pixel_src -> dsi_pll_pixel: %d\n", ret); + + return dsi_link_clk_set_rate_6g(msm_host); +} int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host) { @@ -598,7 +648,6 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi) DBG("pclk=%lu, bclk=%lu", msm_host->pixel_clk_rate, msm_host->byte_clk_rate); - } int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi) @@ -687,8 +736,8 @@ static inline enum dsi_traffic_mode dsi_get_traffic_mode(const u32 mode_flags) return NON_BURST_SYNCH_EVENT; } -static inline enum dsi_vid_dst_format dsi_get_vid_fmt( - const enum mipi_dsi_pixel_format mipi_fmt) +static inline enum dsi_vid_dst_format +dsi_get_vid_fmt(const enum mipi_dsi_pixel_format mipi_fmt) { switch (mipi_fmt) { case MIPI_DSI_FMT_RGB888: return VID_DST_FORMAT_RGB888; @@ -699,8 +748,8 @@ static inline enum dsi_vid_dst_format dsi_get_vid_fmt( } } -static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt( - const enum mipi_dsi_pixel_format mipi_fmt) +static inline enum dsi_cmd_dst_format +dsi_get_cmd_fmt(const enum mipi_dsi_pixel_format mipi_fmt) { switch (mipi_fmt) { case MIPI_DSI_FMT_RGB888: return CMD_DST_FORMAT_RGB888; @@ -846,7 +895,7 @@ static void dsi_ctrl_enable(struct msm_dsi_host *msm_host, dsi_write(msm_host, REG_DSI_CPHY_MODE_CTRL, BIT(0)); } -static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode, u32 hdisplay) +static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode) { struct drm_dsc_config *dsc = msm_host->dsc; u32 reg, reg_ctrl, reg_ctrl2; @@ -858,7 +907,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod /* first calculate dsc parameters and then program * compress mode registers */ - slice_per_intf = msm_dsc_get_slices_per_intf(dsc, hdisplay); + slice_per_intf = dsc->slice_count; total_bytes_per_intf = dsc->slice_chunk_size * slice_per_intf; bytes_per_pkt = dsc->slice_chunk_size; /* * slice_per_pkt; */ @@ -991,7 +1040,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) { if (msm_host->dsc) - dsi_update_dsc_timing(msm_host, false, mode->hdisplay); + dsi_update_dsc_timing(msm_host, false); dsi_write(msm_host, REG_DSI_ACTIVE_H, DSI_ACTIVE_H_START(ha_start) | @@ -1012,7 +1061,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) DSI_ACTIVE_VSYNC_VPOS_END(vs_end)); } else { /* command mode */ if (msm_host->dsc) - dsi_update_dsc_timing(msm_host, true, mode->hdisplay); + dsi_update_dsc_timing(msm_host, true); /* image data and 1 byte write_memory_start cmd */ if (!msm_host->dsc) @@ -1158,10 +1207,10 @@ int dsi_tx_buf_alloc_6g(struct msm_dsi_host *msm_host, int size) uint64_t iova; u8 *data; - msm_host->aspace = msm_gem_address_space_get(priv->kms->aspace); + msm_host->vm = drm_gpuvm_get(priv->kms->vm); data = msm_gem_kernel_new(dev, size, MSM_BO_WC, - msm_host->aspace, + msm_host->vm, &msm_host->tx_gem_obj, &iova); if (IS_ERR(data)) { @@ -1205,10 +1254,10 @@ void msm_dsi_tx_buf_free(struct mipi_dsi_host *host) return; if (msm_host->tx_gem_obj) { - msm_gem_kernel_put(msm_host->tx_gem_obj, msm_host->aspace); - msm_gem_address_space_put(msm_host->aspace); + msm_gem_kernel_put(msm_host->tx_gem_obj, msm_host->vm); + drm_gpuvm_put(msm_host->vm); msm_host->tx_gem_obj = NULL; - msm_host->aspace = NULL; + msm_host->vm = NULL; } if (msm_host->tx_buf) @@ -1292,14 +1341,15 @@ static int dsi_cmd_dma_add(struct msm_dsi_host *msm_host, static int dsi_short_read1_resp(u8 *buf, const struct mipi_dsi_msg *msg) { u8 *data = msg->rx_buf; + if (data && (msg->rx_len >= 1)) { *data = buf[1]; /* strip out dcs type */ return 1; - } else { - pr_err("%s: read data does not match with rx_buf len %zu\n", - __func__, msg->rx_len); - return -EINVAL; } + + pr_err("%s: read data does not match with rx_buf len %zu\n", + __func__, msg->rx_len); + return -EINVAL; } /* @@ -1308,15 +1358,16 @@ static int dsi_short_read1_resp(u8 *buf, const struct mipi_dsi_msg *msg) static int dsi_short_read2_resp(u8 *buf, const struct mipi_dsi_msg *msg) { u8 *data = msg->rx_buf; + if (data && (msg->rx_len >= 2)) { data[0] = buf[1]; /* strip out dcs type */ data[1] = buf[2]; return 2; - } else { - pr_err("%s: read data does not match with rx_buf len %zu\n", - __func__, msg->rx_len); - return -EINVAL; } + + pr_err("%s: read data does not match with rx_buf len %zu\n", + __func__, msg->rx_len); + return -EINVAL; } static int dsi_long_read_resp(u8 *buf, const struct mipi_dsi_msg *msg) @@ -1337,7 +1388,7 @@ int dsi_dma_base_get_6g(struct msm_dsi_host *msm_host, uint64_t *dma_base) return -EINVAL; return msm_gem_get_and_pin_iova(msm_host->tx_gem_obj, - priv->kms->aspace, dma_base); + priv->kms->vm, dma_base); } int dsi_dma_base_get_v2(struct msm_dsi_host *msm_host, uint64_t *dma_base) @@ -1376,8 +1427,9 @@ static int dsi_cmd_dma_tx(struct msm_dsi_host *msm_host, int len) ret = -ETIMEDOUT; else ret = len; - } else + } else { ret = len; + } return ret; } @@ -1445,11 +1497,12 @@ static int dsi_cmds2buf_tx(struct msm_dsi_host *msm_host, return len; } - /* for video mode, do not send cmds more than - * one pixel line, since it only transmit it - * during BLLP. - */ - /* TODO: if the command is sent in LP mode, the bit rate is only + /* + * for video mode, do not send cmds more than + * one pixel line, since it only transmit it + * during BLLP. + * + * TODO: if the command is sent in LP mode, the bit rate is only * half of esc clk rate. In this case, if the video is already * actively streaming, we need to check more carefully if the * command can be fit into one BLLP. @@ -1767,8 +1820,20 @@ static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct drm_dsc return -EINVAL; } - if (dsc->bits_per_component != 8) { - DRM_DEV_ERROR(&msm_host->pdev->dev, "DSI does not support bits_per_component != 8 yet\n"); + switch (dsc->bits_per_component) { + case 8: + case 10: + case 12: + /* + * Only 8, 10, and 12 bpc are supported for DSC 1.1 block. + * If additional bpc values need to be supported, update + * this quard with the appropriate DSC version verification. + */ + break; + default: + DRM_DEV_ERROR(&msm_host->pdev->dev, + "Unsupported bits_per_component value: %d\n", + dsc->bits_per_component); return -EOPNOTSUPP; } @@ -1779,7 +1844,7 @@ static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct drm_dsc drm_dsc_set_const_params(dsc); drm_dsc_set_rc_buf_thresh(dsc); - /* handle only bpp = bpc = 8, pre-SCR panels */ + /* DPU supports only pre-SCR panels */ ret = drm_dsc_setup_rc_params(dsc, DRM_DSC_1_1_PRE_SCR); if (ret) { DRM_DEV_ERROR(&msm_host->pdev->dev, "could not find DSC RC parameters\n"); @@ -1827,11 +1892,18 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host) __func__, ret); goto err; } - if (!ret) + if (!ret) { msm_dsi->te_source = devm_kstrdup(dev, te_source, GFP_KERNEL); + if (!msm_dsi->te_source) { + DRM_DEV_ERROR(dev, "%s: failed to allocate te_source\n", + __func__); + ret = -ENOMEM; + goto err; + } + } ret = 0; - if (of_property_read_bool(np, "syscon-sfpb")) { + if (of_property_present(np, "syscon-sfpb")) { msm_host->sfpb = syscon_regmap_lookup_by_phandle(np, "syscon-sfpb"); if (IS_ERR(msm_host->sfpb)) { @@ -1874,39 +1946,35 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) int ret; msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL); - if (!msm_host) { + if (!msm_host) return -ENOMEM; - } msm_host->pdev = pdev; msm_dsi->host = &msm_host->base; ret = dsi_host_parse_dt(msm_host); - if (ret) { - pr_err("%s: failed to parse dt\n", __func__); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "%s: failed to parse dt\n", + __func__); msm_host->ctrl_base = msm_ioremap_size(pdev, "dsi_ctrl", &msm_host->ctrl_size); - if (IS_ERR(msm_host->ctrl_base)) { - pr_err("%s: unable to map Dsi ctrl base\n", __func__); - return PTR_ERR(msm_host->ctrl_base); - } + if (IS_ERR(msm_host->ctrl_base)) + return dev_err_probe(&pdev->dev, PTR_ERR(msm_host->ctrl_base), + "%s: unable to map Dsi ctrl base\n", __func__); pm_runtime_enable(&pdev->dev); msm_host->cfg_hnd = dsi_get_config(msm_host); - if (!msm_host->cfg_hnd) { - pr_err("%s: get config failed\n", __func__); - return -EINVAL; - } + if (!msm_host->cfg_hnd) + return dev_err_probe(&pdev->dev, -EINVAL, + "%s: get config failed\n", __func__); cfg = msm_host->cfg_hnd->cfg; msm_host->id = dsi_host_get_id(msm_host); - if (msm_host->id < 0) { - pr_err("%s: unable to identify DSI host index\n", __func__); - return msm_host->id; - } + if (msm_host->id < 0) + return dev_err_probe(&pdev->dev, msm_host->id, + "%s: unable to identify DSI host index\n", + __func__); /* fixup base address by io offset */ msm_host->ctrl_base += cfg->io_offset; @@ -1918,42 +1986,32 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) return ret; ret = dsi_clk_init(msm_host); - if (ret) { - pr_err("%s: unable to initialize dsi clks\n", __func__); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "%s: unable to initialize dsi clks\n", __func__); msm_host->rx_buf = devm_kzalloc(&pdev->dev, SZ_4K, GFP_KERNEL); - if (!msm_host->rx_buf) { - pr_err("%s: alloc rx temp buf failed\n", __func__); + if (!msm_host->rx_buf) return -ENOMEM; - } ret = devm_pm_opp_set_clkname(&pdev->dev, "byte"); if (ret) return ret; /* OPP table is optional */ ret = devm_pm_opp_of_add_table(&pdev->dev); - if (ret && ret != -ENODEV) { - dev_err(&pdev->dev, "invalid OPP table in device tree\n"); - return ret; - } + if (ret && ret != -ENODEV) + return dev_err_probe(&pdev->dev, ret, "invalid OPP table in device tree\n"); msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); - if (!msm_host->irq) { - dev_err(&pdev->dev, "failed to get irq\n"); - return -EINVAL; - } + if (!msm_host->irq) + return dev_err_probe(&pdev->dev, -EINVAL, "failed to get irq\n"); /* do not autoenable, will be enabled later */ ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN, "dsi_isr", msm_host); - if (ret < 0) { - dev_err(&pdev->dev, "failed to request IRQ%u: %d\n", - msm_host->irq, ret); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "failed to request IRQ%u\n", + msm_host->irq); init_completion(&msm_host->dma_comp); init_completion(&msm_host->video_comp); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index a210b7c9e5ca..ca400924d4ee 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -74,17 +74,35 @@ static int dsi_mgr_setup_components(int id) int ret; if (!IS_BONDED_DSI()) { + /* + * Set the usecase before calling msm_dsi_host_register(), which would + * already program the PLL source mux based on a default usecase. + */ + msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE); + msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); + ret = msm_dsi_host_register(msm_dsi->host); if (ret) return ret; - - msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE); - msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); } else if (other_dsi) { struct msm_dsi *master_link_dsi = IS_MASTER_DSI_LINK(id) ? msm_dsi : other_dsi; struct msm_dsi *slave_link_dsi = IS_MASTER_DSI_LINK(id) ? other_dsi : msm_dsi; + + /* + * PLL0 is to drive both DSI link clocks in bonded DSI mode. + * + * Set the usecase before calling msm_dsi_host_register(), which would + * already program the PLL source mux based on a default usecase. + */ + msm_dsi_phy_set_usecase(clk_master_dsi->phy, + MSM_DSI_PHY_MASTER); + msm_dsi_phy_set_usecase(clk_slave_dsi->phy, + MSM_DSI_PHY_SLAVE); + msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); + msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy); + /* Register slave host first, so that slave DSI device * has a chance to probe, and do not block the master * DSI device's probe. @@ -98,14 +116,6 @@ static int dsi_mgr_setup_components(int id) ret = msm_dsi_host_register(master_link_dsi->host); if (ret) return ret; - - /* PLL0 is to drive both 2 DSI link clocks in bonded DSI mode. */ - msm_dsi_phy_set_usecase(clk_master_dsi->phy, - MSM_DSI_PHY_MASTER); - msm_dsi_phy_set_usecase(clk_slave_dsi->phy, - MSM_DSI_PHY_SLAVE); - msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); - msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy); } return 0; @@ -424,12 +434,13 @@ static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge, } static int dsi_mgr_bridge_attach(struct drm_bridge *bridge, + struct drm_encoder *encoder, enum drm_bridge_attach_flags flags) { int id = dsi_mgr_bridge_get_id(bridge); struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - return drm_bridge_attach(bridge->encoder, msm_dsi->next_bridge, + return drm_bridge_attach(encoder, msm_dsi->next_bridge, bridge, flags); } @@ -451,15 +462,14 @@ int msm_dsi_manager_connector_init(struct msm_dsi *msm_dsi, struct drm_connector *connector; int ret; - dsi_bridge = devm_kzalloc(msm_dsi->dev->dev, - sizeof(*dsi_bridge), GFP_KERNEL); - if (!dsi_bridge) - return -ENOMEM; + dsi_bridge = devm_drm_bridge_alloc(msm_dsi->dev->dev, struct dsi_bridge, base, + &dsi_mgr_bridge_funcs); + if (IS_ERR(dsi_bridge)) + return PTR_ERR(dsi_bridge); dsi_bridge->id = msm_dsi->id; bridge = &dsi_bridge->base; - bridge->funcs = &dsi_mgr_bridge_funcs; ret = devm_drm_bridge_add(msm_dsi->dev->dev, bridge); if (ret) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index dd58bc0a49eb..4ea681130dba 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -5,6 +5,8 @@ #include <linux/clk-provider.h> #include <linux/platform_device.h> +#include <linux/pm_clock.h> +#include <linux/pm_runtime.h> #include <dt-bindings/phy/phy.h> #include "dsi_phy.h" @@ -511,30 +513,6 @@ int msm_dsi_cphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing, return 0; } -static int dsi_phy_enable_resource(struct msm_dsi_phy *phy) -{ - struct device *dev = &phy->pdev->dev; - int ret; - - ret = pm_runtime_resume_and_get(dev); - if (ret) - return ret; - - ret = clk_prepare_enable(phy->ahb_clk); - if (ret) { - DRM_DEV_ERROR(dev, "%s: can't enable ahb clk, %d\n", __func__, ret); - pm_runtime_put_sync(dev); - } - - return ret; -} - -static void dsi_phy_disable_resource(struct msm_dsi_phy *phy) -{ - clk_disable_unprepare(phy->ahb_clk); - pm_runtime_put(&phy->pdev->dev); -} - static const struct of_device_id dsi_phy_dt_match[] = { #ifdef CONFIG_DRM_MSM_DSI_28NM_PHY { .compatible = "qcom,dsi-phy-28nm-hpm", @@ -567,6 +545,8 @@ static const struct of_device_id dsi_phy_dt_match[] = { .data = &dsi_phy_14nm_8953_cfgs }, { .compatible = "qcom,sm6125-dsi-phy-14nm", .data = &dsi_phy_14nm_2290_cfgs }, + { .compatible = "qcom,sm6150-dsi-phy-14nm", + .data = &dsi_phy_14nm_6150_cfgs }, #endif #ifdef CONFIG_DRM_MSM_DSI_10NM_PHY { .compatible = "qcom,dsi-phy-10nm", @@ -579,6 +559,10 @@ static const struct of_device_id dsi_phy_dt_match[] = { .data = &dsi_phy_7nm_cfgs }, { .compatible = "qcom,dsi-phy-7nm-8150", .data = &dsi_phy_7nm_8150_cfgs }, + { .compatible = "qcom,sa8775p-dsi-phy-5nm", + .data = &dsi_phy_5nm_8775p_cfgs }, + { .compatible = "qcom,sar2130p-dsi-phy-5nm", + .data = &dsi_phy_5nm_sar2130p_cfgs }, { .compatible = "qcom,sc7280-dsi-phy-7nm", .data = &dsi_phy_7nm_7280_cfgs }, { .compatible = "qcom,sm6375-dsi-phy-7nm", @@ -591,6 +575,8 @@ static const struct of_device_id dsi_phy_dt_match[] = { .data = &dsi_phy_4nm_8550_cfgs }, { .compatible = "qcom,sm8650-dsi-phy-4nm", .data = &dsi_phy_4nm_8650_cfgs }, + { .compatible = "qcom,sm8750-dsi-phy-3nm", + .data = &dsi_phy_3nm_8750_cfgs }, #endif {} }; @@ -690,22 +676,20 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) if (ret) return ret; - phy->ahb_clk = msm_clk_get(pdev, "iface"); - if (IS_ERR(phy->ahb_clk)) - return dev_err_probe(dev, PTR_ERR(phy->ahb_clk), - "Unable to get ahb clk\n"); + platform_set_drvdata(pdev, phy); - ret = devm_pm_runtime_enable(&pdev->dev); + ret = devm_pm_runtime_enable(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. - */ - ret = dsi_phy_enable_resource(phy); + ret = devm_pm_clk_create(dev); if (ret) return ret; + ret = pm_clk_add(dev, "iface"); + if (ret < 0) + return dev_err_probe(dev, ret, "Unable to get iface clk\n"); + if (phy->cfg->ops.pll_init) { ret = phy->cfg->ops.pll_init(phy); if (ret) @@ -719,18 +703,19 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "Failed to register clk provider\n"); - dsi_phy_disable_resource(phy); - - platform_set_drvdata(pdev, phy); - return 0; } +static const struct dev_pm_ops dsi_phy_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + static struct platform_driver dsi_phy_platform_driver = { .probe = dsi_phy_driver_probe, .driver = { .name = "msm_dsi_phy", .of_match_table = dsi_phy_dt_match, + .pm = &dsi_phy_pm_ops, }, }; @@ -756,9 +741,9 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, dev = &phy->pdev->dev; - ret = dsi_phy_enable_resource(phy); + ret = pm_runtime_resume_and_get(dev); if (ret) { - DRM_DEV_ERROR(dev, "%s: resource enable failed, %d\n", + DRM_DEV_ERROR(dev, "%s: resume failed, %d\n", __func__, ret); goto res_en_fail; } @@ -802,7 +787,7 @@ pll_restor_fail: phy_en_fail: regulator_bulk_disable(phy->cfg->num_regulators, phy->supplies); reg_en_fail: - dsi_phy_disable_resource(phy); + pm_runtime_put(dev); res_en_fail: return ret; } @@ -815,7 +800,7 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy) phy->cfg->ops.disable(phy); regulator_bulk_disable(phy->cfg->num_regulators, phy->supplies); - dsi_phy_disable_resource(phy); + pm_runtime_put(&phy->pdev->dev); } void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h index 4953459edd63..3cbf08231492 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h @@ -6,6 +6,7 @@ #ifndef __DSI_PHY_H__ #define __DSI_PHY_H__ +#include <dt-bindings/clock/qcom,dsi-phy-28nm.h> #include <linux/clk-provider.h> #include <linux/delay.h> #include <linux/regulator/consumer.h> @@ -46,6 +47,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8937_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_14nm_6150_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_14nm_2290_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs; @@ -57,8 +59,11 @@ extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8775p_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_3nm_8750_cfgs; struct msm_dsi_dphy_timing { u32 clk_zero; @@ -83,9 +88,7 @@ struct msm_dsi_dphy_timing { u8 hs_halfbyte_en_ckln; }; -#define DSI_BYTE_PLL_CLK 0 -#define DSI_PIXEL_PLL_CLK 1 -#define NUM_PROVIDED_CLKS 2 +#define NUM_PROVIDED_CLKS (DSI_PIXEL_PLL_CLK + 1) #define DSI_LANE_MAX 5 @@ -101,7 +104,6 @@ struct msm_dsi_phy { phys_addr_t lane_size; int id; - struct clk *ahb_clk; struct regulator_bulk_data *supplies; struct msm_dsi_dphy_timing timing; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c index 677c62571811..ec486ff02c9b 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c @@ -3,6 +3,7 @@ * Copyright (c) 2018, The Linux Foundation */ +#include <dt-bindings/clock/qcom,dsi-phy-28nm.h> #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/iopoll.h> @@ -443,21 +444,19 @@ static unsigned long dsi_pll_10nm_vco_recalc_rate(struct clk_hw *hw, return (unsigned long)vco_rate; } -static long dsi_pll_10nm_clk_round_rate(struct clk_hw *hw, - unsigned long rate, unsigned long *parent_rate) +static int dsi_pll_10nm_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct dsi_pll_10nm *pll_10nm = to_pll_10nm(hw); - if (rate < pll_10nm->phy->cfg->min_pll_rate) - return pll_10nm->phy->cfg->min_pll_rate; - else if (rate > pll_10nm->phy->cfg->max_pll_rate) - return pll_10nm->phy->cfg->max_pll_rate; - else - return rate; + req->rate = clamp_t(unsigned long, req->rate, + pll_10nm->phy->cfg->min_pll_rate, pll_10nm->phy->cfg->max_pll_rate); + + return 0; } static const struct clk_ops clk_ops_dsi_pll_10nm_vco = { - .round_rate = dsi_pll_10nm_clk_round_rate, + .determine_rate = dsi_pll_10nm_clk_determine_rate, .set_rate = dsi_pll_10nm_vco_set_rate, .recalc_rate = dsi_pll_10nm_vco_recalc_rate, .prepare = dsi_pll_10nm_vco_prepare, @@ -703,6 +702,13 @@ static int dsi_pll_10nm_init(struct msm_dsi_phy *phy) /* TODO: Remove this when we have proper display handover support */ msm_dsi_phy_pll_save_state(phy); + /* + * Store also proper vco_current_rate, because its value will be used in + * dsi_10nm_pll_restore_state(). + */ + if (!dsi_pll_10nm_vco_recalc_rate(&pll_10nm->clk_hw, VCO_REF_CLK_RATE)) + pll_10nm->vco_current_rate = pll_10nm->phy->cfg->min_pll_rate; + return 0; } diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index 1723f0e4faa4..fdefcbd9c284 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -3,6 +3,7 @@ * Copyright (c) 2016, The Linux Foundation. All rights reserved. */ +#include <dt-bindings/clock/qcom,dsi-phy-28nm.h> #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/delay.h> @@ -577,21 +578,19 @@ static void dsi_pll_14nm_vco_unprepare(struct clk_hw *hw) pll_14nm->phy->pll_on = false; } -static long dsi_pll_14nm_clk_round_rate(struct clk_hw *hw, - unsigned long rate, unsigned long *parent_rate) +static int dsi_pll_14nm_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct dsi_pll_14nm *pll_14nm = to_pll_14nm(hw); - if (rate < pll_14nm->phy->cfg->min_pll_rate) - return pll_14nm->phy->cfg->min_pll_rate; - else if (rate > pll_14nm->phy->cfg->max_pll_rate) - return pll_14nm->phy->cfg->max_pll_rate; - else - return rate; + req->rate = clamp_t(unsigned long, req->rate, + pll_14nm->phy->cfg->min_pll_rate, pll_14nm->phy->cfg->max_pll_rate); + + return 0; } static const struct clk_ops clk_ops_dsi_pll_14nm_vco = { - .round_rate = dsi_pll_14nm_clk_round_rate, + .determine_rate = dsi_pll_14nm_clk_determine_rate, .set_rate = dsi_pll_14nm_vco_set_rate, .recalc_rate = dsi_pll_14nm_vco_recalc_rate, .prepare = dsi_pll_14nm_vco_prepare, @@ -621,18 +620,20 @@ static unsigned long dsi_pll_14nm_postdiv_recalc_rate(struct clk_hw *hw, postdiv->flags, width); } -static long dsi_pll_14nm_postdiv_round_rate(struct clk_hw *hw, - unsigned long rate, - unsigned long *prate) +static int dsi_pll_14nm_postdiv_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw); struct dsi_pll_14nm *pll_14nm = postdiv->pll; - DBG("DSI%d PLL parent rate=%lu", pll_14nm->phy->id, rate); + DBG("DSI%d PLL parent rate=%lu", pll_14nm->phy->id, req->rate); - return divider_round_rate(hw, rate, prate, NULL, - postdiv->width, - postdiv->flags); + req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, + NULL, + postdiv->width, + postdiv->flags); + + return 0; } static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, @@ -679,7 +680,7 @@ static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, static const struct clk_ops clk_ops_dsi_pll_14nm_postdiv = { .recalc_rate = dsi_pll_14nm_postdiv_recalc_rate, - .round_rate = dsi_pll_14nm_postdiv_round_rate, + .determine_rate = dsi_pll_14nm_postdiv_determine_rate, .set_rate = dsi_pll_14nm_postdiv_set_rate, }; @@ -1032,6 +1033,10 @@ static const struct regulator_bulk_data dsi_phy_14nm_73p4mA_regulators[] = { { .supply = "vcca", .init_load_uA = 73400 }, }; +static const struct regulator_bulk_data dsi_phy_14nm_36mA_regulators[] = { + { .supply = "vdda", .init_load_uA = 36000 }, +}; + const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs = { .has_phy_lane = true, .regulator_data = dsi_phy_14nm_17mA_regulators, @@ -1097,3 +1102,20 @@ const struct msm_dsi_phy_cfg dsi_phy_14nm_2290_cfgs = { .io_start = { 0x5e94400 }, .num_dsi_phy = 1, }; + +const struct msm_dsi_phy_cfg dsi_phy_14nm_6150_cfgs = { + .has_phy_lane = true, + .regulator_data = dsi_phy_14nm_36mA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_14nm_36mA_regulators), + .ops = { + .enable = dsi_14nm_phy_enable, + .disable = dsi_14nm_phy_disable, + .pll_init = dsi_pll_14nm_init, + .save_pll_state = dsi_14nm_pll_save_state, + .restore_pll_state = dsi_14nm_pll_restore_state, + }, + .min_pll_rate = VCO_MIN_RATE, + .max_pll_rate = VCO_MAX_RATE, + .io_start = { 0xae94400 }, + .num_dsi_phy = 1, +}; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c index 1383e3a4e050..d00e415b9a99 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c @@ -3,6 +3,7 @@ * Copyright (c) 2015, The Linux Foundation. All rights reserved. */ +#include <dt-bindings/clock/qcom,dsi-phy-28nm.h> #include <linux/clk.h> #include <linux/clk-provider.h> @@ -532,21 +533,20 @@ static void dsi_pll_28nm_vco_unprepare(struct clk_hw *hw) pll_28nm->phy->pll_on = false; } -static long dsi_pll_28nm_clk_round_rate(struct clk_hw *hw, - unsigned long rate, unsigned long *parent_rate) +static int dsi_pll_28nm_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw); - if (rate < pll_28nm->phy->cfg->min_pll_rate) - return pll_28nm->phy->cfg->min_pll_rate; - else if (rate > pll_28nm->phy->cfg->max_pll_rate) - return pll_28nm->phy->cfg->max_pll_rate; - else - return rate; + req->rate = clamp_t(unsigned long, req->rate, + pll_28nm->phy->cfg->min_pll_rate, + pll_28nm->phy->cfg->max_pll_rate); + + return 0; } static const struct clk_ops clk_ops_dsi_pll_28nm_vco_hpm = { - .round_rate = dsi_pll_28nm_clk_round_rate, + .determine_rate = dsi_pll_28nm_clk_determine_rate, .set_rate = dsi_pll_28nm_clk_set_rate, .recalc_rate = dsi_pll_28nm_clk_recalc_rate, .prepare = dsi_pll_28nm_vco_prepare_hpm, @@ -555,7 +555,7 @@ static const struct clk_ops clk_ops_dsi_pll_28nm_vco_hpm = { }; static const struct clk_ops clk_ops_dsi_pll_28nm_vco_lp = { - .round_rate = dsi_pll_28nm_clk_round_rate, + .determine_rate = dsi_pll_28nm_clk_determine_rate, .set_rate = dsi_pll_28nm_clk_set_rate, .recalc_rate = dsi_pll_28nm_clk_recalc_rate, .prepare = dsi_pll_28nm_vco_prepare_lp, @@ -564,7 +564,7 @@ static const struct clk_ops clk_ops_dsi_pll_28nm_vco_lp = { }; static const struct clk_ops clk_ops_dsi_pll_28nm_vco_8226 = { - .round_rate = dsi_pll_28nm_clk_round_rate, + .determine_rate = dsi_pll_28nm_clk_determine_rate, .set_rate = dsi_pll_28nm_clk_set_rate, .recalc_rate = dsi_pll_28nm_clk_recalc_rate, .prepare = dsi_pll_28nm_vco_prepare_8226, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c index 5311ab7f3c70..8dcce9581dc3 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c @@ -3,6 +3,7 @@ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. */ +#include <dt-bindings/clock/qcom,dsi-phy-28nm.h> #include <linux/clk-provider.h> #include <linux/delay.h> @@ -230,21 +231,19 @@ static void dsi_pll_28nm_vco_unprepare(struct clk_hw *hw) pll_28nm->phy->pll_on = false; } -static long dsi_pll_28nm_clk_round_rate(struct clk_hw *hw, - unsigned long rate, unsigned long *parent_rate) +static int dsi_pll_28nm_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw); - if (rate < pll_28nm->phy->cfg->min_pll_rate) - return pll_28nm->phy->cfg->min_pll_rate; - else if (rate > pll_28nm->phy->cfg->max_pll_rate) - return pll_28nm->phy->cfg->max_pll_rate; - else - return rate; + req->rate = clamp_t(unsigned long, req->rate, + pll_28nm->phy->cfg->min_pll_rate, pll_28nm->phy->cfg->max_pll_rate); + + return 0; } static const struct clk_ops clk_ops_dsi_pll_28nm_vco = { - .round_rate = dsi_pll_28nm_clk_round_rate, + .determine_rate = dsi_pll_28nm_clk_determine_rate, .set_rate = dsi_pll_28nm_clk_set_rate, .recalc_rate = dsi_pll_28nm_clk_recalc_rate, .prepare = dsi_pll_28nm_vco_prepare, @@ -295,18 +294,20 @@ static unsigned int get_vco_mul_factor(unsigned long byte_clk_rate) return 8; } -static long clk_bytediv_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_bytediv_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { unsigned long best_parent; unsigned int factor; - factor = get_vco_mul_factor(rate); + factor = get_vco_mul_factor(req->rate); + + best_parent = req->rate * factor; + req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent); - best_parent = rate * factor; - *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent); + req->rate = req->best_parent_rate / factor; - return *prate / factor; + return 0; } static int clk_bytediv_set_rate(struct clk_hw *hw, unsigned long rate, @@ -327,7 +328,7 @@ static int clk_bytediv_set_rate(struct clk_hw *hw, unsigned long rate, /* Our special byte clock divider ops */ static const struct clk_ops clk_bytediv_ops = { - .round_rate = clk_bytediv_round_rate, + .determine_rate = clk_bytediv_determine_rate, .set_rate = clk_bytediv_set_rate, .recalc_rate = clk_bytediv_recalc_rate, }; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index 031446c87dae..c5e1d2016bcc 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -3,6 +3,8 @@ * Copyright (c) 2018, The Linux Foundation */ +#include <dt-bindings/clock/qcom,dsi-phy-28nm.h> +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/iopoll.h> @@ -49,6 +51,8 @@ #define DSI_PHY_7NM_QUIRK_V4_3 BIT(3) /* Hardware is V5.2 */ #define DSI_PHY_7NM_QUIRK_V5_2 BIT(4) +/* Hardware is V7.0 */ +#define DSI_PHY_7NM_QUIRK_V7_0 BIT(5) struct dsi_pll_config { bool enable_ssc; @@ -83,6 +87,16 @@ struct dsi_pll_7nm { /* protects REG_DSI_7nm_PHY_CMN_CLK_CFG0 register */ spinlock_t postdiv_lock; + /* protects REG_DSI_7nm_PHY_CMN_CLK_CFG1 register */ + spinlock_t pclk_mux_lock; + + /* + * protects REG_DSI_7nm_PHY_CMN_CTRL_0 register and pll_enable_cnt + * member + */ + spinlock_t pll_enable_lock; + int pll_enable_cnt; + struct pll_7nm_cached_state cached_state; struct dsi_pll_7nm *slave; @@ -96,6 +110,9 @@ struct dsi_pll_7nm { */ static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX]; +static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll); +static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll); + static void dsi_pll_setup_config(struct dsi_pll_config *config) { config->ssc_freq = 31500; @@ -124,9 +141,30 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, struct dsi_pll_config dec_multiple = div_u64(pll_freq * multiplier, divider); dec = div_u64_rem(dec_multiple, multiplier, &frac); - if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1) + if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1) { config->pll_clock_inverters = 0x28; - else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { + } else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) { + if (pll_freq < 163000000ULL) + config->pll_clock_inverters = 0xa0; + else if (pll_freq < 175000000ULL) + config->pll_clock_inverters = 0x20; + else if (pll_freq < 325000000ULL) + config->pll_clock_inverters = 0xa0; + else if (pll_freq < 350000000ULL) + config->pll_clock_inverters = 0x20; + else if (pll_freq < 650000000ULL) + config->pll_clock_inverters = 0xa0; + else if (pll_freq < 700000000ULL) + config->pll_clock_inverters = 0x20; + else if (pll_freq < 1300000000ULL) + config->pll_clock_inverters = 0xa0; + else if (pll_freq < 2500000000ULL) + config->pll_clock_inverters = 0x20; + else if (pll_freq < 4000000000ULL) + config->pll_clock_inverters = 0x00; + else + config->pll_clock_inverters = 0x40; + } else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { if (pll_freq <= 1300000000ULL) config->pll_clock_inverters = 0xa0; else if (pll_freq <= 2500000000ULL) @@ -245,7 +283,8 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll) vco_config_1 = 0x01; } - if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { + if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || + (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) { if (pll->vco_current_rate < 1557000000ULL) vco_config_1 = 0x08; else @@ -302,7 +341,7 @@ static void dsi_pll_commit(struct dsi_pll_7nm *pll, struct dsi_pll_config *confi writel(pll->phy->cphy_mode ? 0x00 : 0x10, base + REG_DSI_7nm_PHY_PLL_CMODE_1); writel(config->pll_clock_inverters, - base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS); + base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS_1); } static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate, @@ -311,6 +350,7 @@ static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate, struct dsi_pll_7nm *pll_7nm = to_pll_7nm(hw); struct dsi_pll_config config; + dsi_pll_enable_pll_bias(pll_7nm); DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_7nm->phy->id, rate, parent_rate); @@ -328,6 +368,7 @@ static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate, dsi_pll_ssc_commit(pll_7nm, &config); + dsi_pll_disable_pll_bias(pll_7nm); /* flush, ensure all register writes are done*/ wmb(); @@ -356,38 +397,82 @@ static int dsi_pll_7nm_lock_status(struct dsi_pll_7nm *pll) static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll) { - u32 data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); + unsigned long flags; + u32 data; + + spin_lock_irqsave(&pll->pll_enable_lock, flags); + --pll->pll_enable_cnt; + if (pll->pll_enable_cnt < 0) { + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); + DRM_DEV_ERROR_RATELIMITED(&pll->phy->pdev->dev, + "bug: imbalance in disabling PLL bias\n"); + return; + } else if (pll->pll_enable_cnt > 0) { + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); + return; + } /* else: == 0 */ + data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); + data &= ~DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; writel(0, pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES); - writel(data & ~BIT(5), pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); + writel(data, pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); ndelay(250); } static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll) { - u32 data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); + unsigned long flags; + u32 data; + + spin_lock_irqsave(&pll->pll_enable_lock, flags); + pll->pll_enable_cnt++; + WARN_ON(pll->pll_enable_cnt == INT_MAX); + + data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); + data |= DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; + writel(data, pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); - writel(data | BIT(5), pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); writel(0xc0, pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES); + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); ndelay(250); } -static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll) +static void dsi_pll_cmn_clk_cfg0_write(struct dsi_pll_7nm *pll, u32 val) +{ + unsigned long flags; + + spin_lock_irqsave(&pll->postdiv_lock, flags); + writel(val, pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG0); + spin_unlock_irqrestore(&pll->postdiv_lock, flags); +} + +static void dsi_pll_cmn_clk_cfg1_update(struct dsi_pll_7nm *pll, u32 mask, + u32 val) { + unsigned long flags; u32 data; + spin_lock_irqsave(&pll->pclk_mux_lock, flags); data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); - writel(data & ~BIT(5), pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); + data &= ~mask; + data |= val & mask; + + writel(data, pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); + spin_unlock_irqrestore(&pll->pclk_mux_lock, flags); +} + +static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll) +{ + dsi_pll_cmn_clk_cfg1_update(pll, DSI_7nm_PHY_CMN_CLK_CFG1_CLK_EN, 0); } static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll) { - u32 data; + u32 cfg_1 = DSI_7nm_PHY_CMN_CLK_CFG1_CLK_EN | DSI_7nm_PHY_CMN_CLK_CFG1_CLK_EN_SEL; writel(0x04, pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_3); - - data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); - writel(data | BIT(5) | BIT(4), pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); + dsi_pll_cmn_clk_cfg1_update(pll, cfg_1, cfg_1); } static void dsi_pll_phy_dig_reset(struct dsi_pll_7nm *pll) @@ -443,6 +528,10 @@ static int dsi_pll_7nm_vco_prepare(struct clk_hw *hw) if (pll_7nm->slave) dsi_pll_enable_global_clk(pll_7nm->slave); + writel(0x1, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL); + if (pll_7nm->slave) + writel(0x1, pll_7nm->slave->phy->base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL); + error: return rc; } @@ -486,6 +575,7 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw, u32 dec; u64 pll_freq, tmp64; + dsi_pll_enable_pll_bias(pll_7nm); dec = readl(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1); dec &= 0xff; @@ -510,24 +600,24 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw, DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x", pll_7nm->phy->id, (unsigned long)vco_rate, dec, frac); + dsi_pll_disable_pll_bias(pll_7nm); + return (unsigned long)vco_rate; } -static long dsi_pll_7nm_clk_round_rate(struct clk_hw *hw, - unsigned long rate, unsigned long *parent_rate) +static int dsi_pll_7nm_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct dsi_pll_7nm *pll_7nm = to_pll_7nm(hw); - if (rate < pll_7nm->phy->cfg->min_pll_rate) - return pll_7nm->phy->cfg->min_pll_rate; - else if (rate > pll_7nm->phy->cfg->max_pll_rate) - return pll_7nm->phy->cfg->max_pll_rate; - else - return rate; + req->rate = clamp_t(unsigned long, req->rate, + pll_7nm->phy->cfg->min_pll_rate, pll_7nm->phy->cfg->max_pll_rate); + + return 0; } static const struct clk_ops clk_ops_dsi_pll_7nm_vco = { - .round_rate = dsi_pll_7nm_clk_round_rate, + .determine_rate = dsi_pll_7nm_clk_determine_rate, .set_rate = dsi_pll_7nm_vco_set_rate, .recalc_rate = dsi_pll_7nm_vco_recalc_rate, .prepare = dsi_pll_7nm_vco_prepare, @@ -545,17 +635,19 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy) void __iomem *phy_base = pll_7nm->phy->base; u32 cmn_clk_cfg0, cmn_clk_cfg1; + dsi_pll_enable_pll_bias(pll_7nm); cached->pll_out_div = readl(pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE); cached->pll_out_div &= 0x3; cmn_clk_cfg0 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0); - cached->bit_clk_div = cmn_clk_cfg0 & 0xf; - cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4; + cached->bit_clk_div = FIELD_GET(DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK, cmn_clk_cfg0); + cached->pix_clk_div = FIELD_GET(DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__MASK, cmn_clk_cfg0); cmn_clk_cfg1 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); - cached->pll_mux = cmn_clk_cfg1 & 0x3; + cached->pll_mux = FIELD_GET(DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK, cmn_clk_cfg1); + dsi_pll_disable_pll_bias(pll_7nm); DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x", pll_7nm->phy->id, cached->pll_out_div, cached->bit_clk_div, cached->pix_clk_div, cached->pll_mux); @@ -565,7 +657,6 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy) { struct dsi_pll_7nm *pll_7nm = to_pll_7nm(phy->vco_hw); struct pll_7nm_cached_state *cached = &pll_7nm->cached_state; - void __iomem *phy_base = pll_7nm->phy->base; u32 val; int ret; @@ -574,13 +665,11 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy) val |= cached->pll_out_div; writel(val, pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE); - writel(cached->bit_clk_div | (cached->pix_clk_div << 4), - phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0); - - val = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); - val &= ~0x3; - val |= cached->pll_mux; - writel(val, phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); + dsi_pll_cmn_clk_cfg0_write(pll_7nm, + DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0(cached->bit_clk_div) | + DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4(cached->pix_clk_div)); + dsi_pll_cmn_clk_cfg1_update(pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK, + cached->pll_mux); ret = dsi_pll_7nm_vco_set_rate(phy->vco_hw, pll_7nm->vco_current_rate, @@ -609,6 +698,9 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy) break; case MSM_DSI_PHY_MASTER: pll_7nm->slave = pll_7nm_list[(pll_7nm->phy->id + 1) % DSI_MAX]; + /* v7.0: Enable ATB_EN0 and alternate clock output to external phy */ + if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0) + writel(0x07, base + REG_DSI_7nm_PHY_CMN_CTRL_5); break; case MSM_DSI_PHY_SLAVE: data = 0x1; /* external PLL */ @@ -618,7 +710,8 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy) } /* set PLL src */ - writel(data << 2, base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); + dsi_pll_cmn_clk_cfg1_update(pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL__MASK, + DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL(data)); return 0; } @@ -718,11 +811,9 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide * don't register a pclk_mux clock and just use post_out_div instead */ if (pll_7nm->phy->cphy_mode) { - u32 data; - - data = readl(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); - writel(data | 3, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); - + dsi_pll_cmn_clk_cfg1_update(pll_7nm, + DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK, + DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL(3)); phy_pll_out_dsi_parent = pll_post_out_div; } else { snprintf(clk_name, sizeof(clk_name), "dsi%d_pclk_mux", pll_7nm->phy->id); @@ -733,7 +824,7 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide pll_by_2_bit, }), 2, 0, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, - 0, 1, 0, NULL); + 0, 1, 0, &pll_7nm->pclk_mux_lock); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -778,6 +869,8 @@ static int dsi_pll_7nm_init(struct msm_dsi_phy *phy) pll_7nm_list[phy->id] = pll_7nm; spin_lock_init(&pll_7nm->postdiv_lock); + spin_lock_init(&pll_7nm->pclk_mux_lock); + spin_lock_init(&pll_7nm->pll_enable_lock); pll_7nm->phy = phy; @@ -791,6 +884,12 @@ static int dsi_pll_7nm_init(struct msm_dsi_phy *phy) /* TODO: Remove this when we have proper display handover support */ msm_dsi_phy_pll_save_state(phy); + /* + * Store also proper vco_current_rate, because its value will be used in + * dsi_7nm_pll_restore_state(). + */ + if (!dsi_pll_7nm_vco_recalc_rate(&pll_7nm->clk_hw, VCO_REF_CLK_RATE)) + pll_7nm->vco_current_rate = pll_7nm->phy->cfg->min_pll_rate; return 0; } @@ -887,7 +986,8 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, /* Request for REFGEN READY */ if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) || - (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { + (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || + (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) { writel(0x1, phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10); udelay(500); } @@ -921,7 +1021,20 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, lane_ctrl0 = 0x1f; } - if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { + if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) { + if (phy->cphy_mode) { + /* TODO: different for second phy */ + vreg_ctrl_0 = 0x57; + vreg_ctrl_1 = 0x41; + glbl_rescode_top_ctrl = 0x3d; + glbl_rescode_bot_ctrl = 0x38; + } else { + vreg_ctrl_0 = 0x56; + vreg_ctrl_1 = 0x19; + glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3c : 0x03; + glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x38 : 0x3c; + } + } else if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { if (phy->cphy_mode) { vreg_ctrl_0 = 0x45; vreg_ctrl_1 = 0x41; @@ -972,7 +1085,8 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, } /* de-assert digital and pll power down */ - data = BIT(6) | BIT(5); + data = DSI_7nm_PHY_CMN_CTRL_0_DIGTOP_PWRDN_B | + DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0); /* Assert PLL core reset */ @@ -983,6 +1097,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, /* program CMN_CTRL_4 for minor_ver 2 chipsets*/ if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || + (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0) || (readl(base + REG_DSI_7nm_PHY_CMN_REVISION_ID0) & (0xf0)) == 0x20) writel(0x04, base + REG_DSI_7nm_PHY_CMN_CTRL_4); @@ -1097,7 +1212,8 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) /* Turn off REFGEN Vote */ if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) || - (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { + (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || + (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) { writel(0x0, base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10); wmb(); /* Delay to ensure HW removes vote before PHY shut down */ @@ -1113,6 +1229,7 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) /* Turn off all PHY blocks */ writel(0x00, base + REG_DSI_7nm_PHY_CMN_CTRL_0); + /* make sure phy is turned off */ wmb(); @@ -1127,6 +1244,10 @@ static const struct regulator_bulk_data dsi_phy_7nm_37750uA_regulators[] = { { .supply = "vdds", .init_load_uA = 37550 }, }; +static const struct regulator_bulk_data dsi_phy_7nm_48000uA_regulators[] = { + { .supply = "vdds", .init_load_uA = 48000 }, +}; + static const struct regulator_bulk_data dsi_phy_7nm_98000uA_regulators[] = { { .supply = "vdds", .init_load_uA = 98000 }, }; @@ -1269,6 +1390,52 @@ const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs = { .quirks = DSI_PHY_7NM_QUIRK_V4_3, }; +const struct msm_dsi_phy_cfg dsi_phy_5nm_8775p_cfgs = { + .has_phy_lane = true, + .regulator_data = dsi_phy_7nm_48000uA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_7nm_48000uA_regulators), + .ops = { + .enable = dsi_7nm_phy_enable, + .disable = dsi_7nm_phy_disable, + .pll_init = dsi_pll_7nm_init, + .save_pll_state = dsi_7nm_pll_save_state, + .restore_pll_state = dsi_7nm_pll_restore_state, + .set_continuous_clock = dsi_7nm_set_continuous_clock, + }, + .min_pll_rate = 600000000UL, +#ifdef CONFIG_64BIT + .max_pll_rate = 5000000000UL, +#else + .max_pll_rate = ULONG_MAX, +#endif + .io_start = { 0xae94400, 0xae96400 }, + .num_dsi_phy = 2, + .quirks = DSI_PHY_7NM_QUIRK_V4_2, +}; + +const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs = { + .has_phy_lane = true, + .regulator_data = dsi_phy_7nm_97800uA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_7nm_97800uA_regulators), + .ops = { + .enable = dsi_7nm_phy_enable, + .disable = dsi_7nm_phy_disable, + .pll_init = dsi_pll_7nm_init, + .save_pll_state = dsi_7nm_pll_save_state, + .restore_pll_state = dsi_7nm_pll_restore_state, + .set_continuous_clock = dsi_7nm_set_continuous_clock, + }, + .min_pll_rate = 600000000UL, +#ifdef CONFIG_64BIT + .max_pll_rate = 5000000000UL, +#else + .max_pll_rate = ULONG_MAX, +#endif + .io_start = { 0xae95000, 0xae97000 }, + .num_dsi_phy = 2, + .quirks = DSI_PHY_7NM_QUIRK_V5_2, +}; + const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs = { .has_phy_lane = true, .regulator_data = dsi_phy_7nm_98400uA_regulators, @@ -1314,3 +1481,26 @@ const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs = { .num_dsi_phy = 2, .quirks = DSI_PHY_7NM_QUIRK_V5_2, }; + +const struct msm_dsi_phy_cfg dsi_phy_3nm_8750_cfgs = { + .has_phy_lane = true, + .regulator_data = dsi_phy_7nm_98000uA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_7nm_98000uA_regulators), + .ops = { + .enable = dsi_7nm_phy_enable, + .disable = dsi_7nm_phy_disable, + .pll_init = dsi_pll_7nm_init, + .save_pll_state = dsi_7nm_pll_save_state, + .restore_pll_state = dsi_7nm_pll_restore_state, + .set_continuous_clock = dsi_7nm_set_continuous_clock, + }, + .min_pll_rate = 600000000UL, +#ifdef CONFIG_64BIT + .max_pll_rate = 5000000000UL, +#else + .max_pll_rate = ULONG_MAX, +#endif + .io_start = { 0xae95000, 0xae97000 }, + .num_dsi_phy = 2, + .quirks = DSI_PHY_7NM_QUIRK_V7_0, +}; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 0bfee41c2e71..5afac09c0d33 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -8,12 +8,14 @@ #include <linux/gpio/consumer.h> #include <linux/of_irq.h> #include <linux/of_platform.h> +#include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <drm/drm_bridge_connector.h> #include <drm/drm_of.h> +#include <drm/display/drm_hdmi_state_helper.h> -#include <sound/hdmi-codec.h> +#include "msm_kms.h" #include "hdmi.h" void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on) @@ -24,7 +26,7 @@ void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on) spin_lock_irqsave(&hdmi->reg_lock, flags); if (power_on) { ctrl |= HDMI_CTRL_ENABLE; - if (!hdmi->hdmi_mode) { + if (!hdmi->connector->display_info.is_hdmi) { ctrl |= HDMI_CTRL_HDMI; hdmi_write(hdmi, REG_HDMI_CTRL, ctrl); ctrl &= ~HDMI_CTRL_HDMI; @@ -165,8 +167,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, hdmi->dev = dev; hdmi->encoder = encoder; - hdmi_audio_infoframe_init(&hdmi->audio.infoframe); - ret = msm_hdmi_bridge_init(hdmi); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to create HDMI bridge: %d\n", ret); @@ -201,12 +201,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, goto fail; } - ret = msm_hdmi_hpd_enable(hdmi->bridge); - if (ret < 0) { - DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret); - goto fail; - } - return 0; fail: @@ -222,135 +216,26 @@ fail: * The hdmi device: */ -#define HDMI_CFG(item, entry) \ - .item ## _names = item ##_names_ ## entry, \ - .item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry) - -static const char *hpd_reg_names_8960[] = {"core-vdda"}; -static const char *hpd_clk_names_8960[] = {"core", "master_iface", "slave_iface"}; +static const char * const pwr_reg_names_8960[] = {"core-vdda"}; +static const char * const pwr_clk_names_8960[] = {"core", "master_iface", "slave_iface"}; static const struct hdmi_platform_config hdmi_tx_8960_config = { - HDMI_CFG(hpd_reg, 8960), - HDMI_CFG(hpd_clk, 8960), + .pwr_reg_names = pwr_reg_names_8960, + .pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names_8960), + .pwr_clk_names = pwr_clk_names_8960, + .pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names_8960), }; -static const char *pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; -static const char *pwr_clk_names_8x74[] = {"extp", "alt_iface"}; -static const char *hpd_clk_names_8x74[] = {"iface", "core", "mdp_core"}; -static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0}; +static const char * const pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; +static const char * const pwr_clk_names_8x74[] = {"iface", "core", "mdp_core", "alt_iface"}; static const struct hdmi_platform_config hdmi_tx_8974_config = { - HDMI_CFG(pwr_reg, 8x74), - HDMI_CFG(pwr_clk, 8x74), - HDMI_CFG(hpd_clk, 8x74), - .hpd_freq = hpd_clk_freq_8x74, + .pwr_reg_names = pwr_reg_names_8x74, + .pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names_8x74), + .pwr_clk_names = pwr_clk_names_8x74, + .pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names_8x74), }; -/* - * HDMI audio codec callbacks - */ -static int msm_hdmi_audio_hw_params(struct device *dev, void *data, - struct hdmi_codec_daifmt *daifmt, - struct hdmi_codec_params *params) -{ - struct hdmi *hdmi = dev_get_drvdata(dev); - unsigned int chan; - unsigned int channel_allocation = 0; - unsigned int rate; - unsigned int level_shift = 0; /* 0dB */ - bool down_mix = false; - - DRM_DEV_DEBUG(dev, "%u Hz, %d bit, %d channels\n", params->sample_rate, - params->sample_width, params->cea.channels); - - switch (params->cea.channels) { - case 2: - /* FR and FL speakers */ - channel_allocation = 0; - chan = MSM_HDMI_AUDIO_CHANNEL_2; - break; - case 4: - /* FC, LFE, FR and FL speakers */ - channel_allocation = 0x3; - chan = MSM_HDMI_AUDIO_CHANNEL_4; - break; - case 6: - /* RR, RL, FC, LFE, FR and FL speakers */ - channel_allocation = 0x0B; - chan = MSM_HDMI_AUDIO_CHANNEL_6; - break; - case 8: - /* FRC, FLC, RR, RL, FC, LFE, FR and FL speakers */ - channel_allocation = 0x1F; - chan = MSM_HDMI_AUDIO_CHANNEL_8; - break; - default: - return -EINVAL; - } - - switch (params->sample_rate) { - case 32000: - rate = HDMI_SAMPLE_RATE_32KHZ; - break; - case 44100: - rate = HDMI_SAMPLE_RATE_44_1KHZ; - break; - case 48000: - rate = HDMI_SAMPLE_RATE_48KHZ; - break; - case 88200: - rate = HDMI_SAMPLE_RATE_88_2KHZ; - break; - case 96000: - rate = HDMI_SAMPLE_RATE_96KHZ; - break; - case 176400: - rate = HDMI_SAMPLE_RATE_176_4KHZ; - break; - case 192000: - rate = HDMI_SAMPLE_RATE_192KHZ; - break; - default: - DRM_DEV_ERROR(dev, "rate[%d] not supported!\n", - params->sample_rate); - return -EINVAL; - } - - msm_hdmi_audio_set_sample_rate(hdmi, rate); - msm_hdmi_audio_info_setup(hdmi, 1, chan, channel_allocation, - level_shift, down_mix); - - return 0; -} - -static void msm_hdmi_audio_shutdown(struct device *dev, void *data) -{ - struct hdmi *hdmi = dev_get_drvdata(dev); - - msm_hdmi_audio_info_setup(hdmi, 0, 0, 0, 0, 0); -} - -static const struct hdmi_codec_ops msm_hdmi_audio_codec_ops = { - .hw_params = msm_hdmi_audio_hw_params, - .audio_shutdown = msm_hdmi_audio_shutdown, -}; - -static struct hdmi_codec_pdata codec_data = { - .ops = &msm_hdmi_audio_codec_ops, - .max_i2s_channels = 8, - .i2s = 1, -}; - -static int msm_hdmi_register_audio_driver(struct hdmi *hdmi, struct device *dev) -{ - hdmi->audio_pdev = platform_device_register_data(dev, - HDMI_CODEC_DRV_NAME, - PLATFORM_DEVID_AUTO, - &codec_data, - sizeof(codec_data)); - return PTR_ERR_OR_ZERO(hdmi->audio_pdev); -} - static int msm_hdmi_bind(struct device *dev, struct device *master, void *data) { struct msm_drm_private *priv = dev_get_drvdata(master); @@ -360,13 +245,7 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data) err = msm_hdmi_init(hdmi); if (err) return err; - priv->hdmi = hdmi; - - err = msm_hdmi_register_audio_driver(hdmi, dev); - if (err) { - DRM_ERROR("Failed to attach an audio codec %d\n", err); - hdmi->audio_pdev = NULL; - } + priv->kms->hdmi = hdmi; return 0; } @@ -376,15 +255,9 @@ static void msm_hdmi_unbind(struct device *dev, struct device *master, { struct msm_drm_private *priv = dev_get_drvdata(master); - if (priv->hdmi) { - 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; + if (priv->kms->hdmi) { + msm_hdmi_destroy(priv->kms->hdmi); + priv->kms->hdmi = NULL; } } @@ -412,6 +285,7 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) hdmi->pdev = pdev; hdmi->config = config; spin_lock_init(&hdmi->reg_lock); + mutex_init(&hdmi->state_mutex); ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 1, 0, NULL, &hdmi->next_bridge); if (ret && ret != -ENODEV) @@ -438,20 +312,6 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) if (hdmi->irq < 0) return hdmi->irq; - hdmi->hpd_regs = devm_kcalloc(&pdev->dev, - config->hpd_reg_cnt, - sizeof(hdmi->hpd_regs[0]), - GFP_KERNEL); - if (!hdmi->hpd_regs) - return -ENOMEM; - - for (i = 0; i < config->hpd_reg_cnt; i++) - hdmi->hpd_regs[i].supply = config->hpd_reg_names[i]; - - ret = devm_regulator_bulk_get(&pdev->dev, config->hpd_reg_cnt, hdmi->hpd_regs); - if (ret) - return dev_err_probe(dev, ret, "failed to get hpd regulators\n"); - hdmi->pwr_regs = devm_kcalloc(&pdev->dev, config->pwr_reg_cnt, sizeof(hdmi->pwr_regs[0]), @@ -466,25 +326,6 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "failed to get pwr regulators\n"); - hdmi->hpd_clks = devm_kcalloc(&pdev->dev, - config->hpd_clk_cnt, - sizeof(hdmi->hpd_clks[0]), - GFP_KERNEL); - if (!hdmi->hpd_clks) - return -ENOMEM; - - for (i = 0; i < config->hpd_clk_cnt; i++) { - struct clk *clk; - - clk = msm_clk_get(pdev, config->hpd_clk_names[i]); - if (IS_ERR(clk)) - return dev_err_probe(dev, PTR_ERR(clk), - "failed to get hpd clk: %s\n", - config->hpd_clk_names[i]); - - hdmi->hpd_clks[i] = clk; - } - hdmi->pwr_clks = devm_kcalloc(&pdev->dev, config->pwr_clk_cnt, sizeof(hdmi->pwr_clks[0]), @@ -492,17 +333,17 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) if (!hdmi->pwr_clks) return -ENOMEM; - for (i = 0; i < config->pwr_clk_cnt; i++) { - struct clk *clk; + for (i = 0; i < config->pwr_clk_cnt; i++) + hdmi->pwr_clks[i].id = config->pwr_clk_names[i]; - clk = msm_clk_get(pdev, config->pwr_clk_names[i]); - if (IS_ERR(clk)) - return dev_err_probe(dev, PTR_ERR(clk), - "failed to get pwr clk: %s\n", - config->pwr_clk_names[i]); + ret = devm_clk_bulk_get(&pdev->dev, config->pwr_clk_cnt, hdmi->pwr_clks); + if (ret) + return ret; - hdmi->pwr_clks[i] = clk; - } + hdmi->extp_clk = devm_clk_get_optional(&pdev->dev, "extp"); + if (IS_ERR(hdmi->extp_clk)) + return dev_err_probe(dev, PTR_ERR(hdmi->extp_clk), + "failed to get extp clock\n"); hdmi->hpd_gpiod = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN); /* This will catch e.g. -EPROBE_DEFER */ @@ -548,6 +389,48 @@ static void msm_hdmi_dev_remove(struct platform_device *pdev) msm_hdmi_put_phy(hdmi); } +static int msm_hdmi_runtime_suspend(struct device *dev) +{ + struct hdmi *hdmi = dev_get_drvdata(dev); + const struct hdmi_platform_config *config = hdmi->config; + + clk_bulk_disable_unprepare(config->pwr_clk_cnt, hdmi->pwr_clks); + + pinctrl_pm_select_sleep_state(dev); + + regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs); + + return 0; +} + +static int msm_hdmi_runtime_resume(struct device *dev) +{ + struct hdmi *hdmi = dev_get_drvdata(dev); + const struct hdmi_platform_config *config = hdmi->config; + int ret; + + ret = regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs); + if (ret) + return ret; + + ret = pinctrl_pm_select_default_state(dev); + if (ret) + goto fail; + + ret = clk_bulk_prepare_enable(config->pwr_clk_cnt, hdmi->pwr_clks); + if (ret) + goto fail; + + return 0; + +fail: + pinctrl_pm_select_sleep_state(dev); + + return ret; +} + +DEFINE_RUNTIME_DEV_PM_OPS(msm_hdmi_pm_ops, msm_hdmi_runtime_suspend, msm_hdmi_runtime_resume, NULL); + static const struct of_device_id msm_hdmi_dt_match[] = { { .compatible = "qcom,hdmi-tx-8998", .data = &hdmi_tx_8974_config }, { .compatible = "qcom,hdmi-tx-8996", .data = &hdmi_tx_8974_config }, @@ -561,10 +444,11 @@ static const struct of_device_id msm_hdmi_dt_match[] = { static struct platform_driver msm_hdmi_driver = { .probe = msm_hdmi_dev_probe, - .remove_new = msm_hdmi_dev_remove, + .remove = msm_hdmi_dev_remove, .driver = { .name = "hdmi_msm", .of_match_table = msm_hdmi_dt_match, + .pm = &msm_hdmi_pm_ops, }, }; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index a62d2aedfbb7..02cfd46df594 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -24,8 +24,8 @@ struct hdmi_platform_config; struct hdmi_audio { bool enabled; - struct hdmi_audio_infoframe infoframe; int rate; + int channels; }; struct hdmi_hdcp_ctrl; @@ -33,7 +33,6 @@ struct hdmi_hdcp_ctrl; struct hdmi { struct drm_device *dev; struct platform_device *pdev; - struct platform_device *audio_pdev; const struct hdmi_platform_config *config; @@ -42,16 +41,17 @@ struct hdmi { /* video state: */ bool power_on; + bool hpd_enabled; + struct mutex state_mutex; /* protects two booleans */ unsigned long int pixclock; void __iomem *mmio; void __iomem *qfprom_mmio; phys_addr_t mmio_phy_addr; - struct regulator_bulk_data *hpd_regs; struct regulator_bulk_data *pwr_regs; - struct clk **hpd_clks; - struct clk **pwr_clks; + struct clk_bulk_data *pwr_clks; + struct clk *extp_clk; struct gpio_desc *hpd_gpiod; @@ -67,8 +67,6 @@ struct hdmi { /* the encoder we are hooked to (outside of hdmi block) */ struct drm_encoder *encoder; - bool hdmi_mode; /* are we in hdmi mode? */ - int irq; struct workqueue_struct *workq; @@ -86,21 +84,12 @@ struct hdmi { /* platform config data (ie. from DT, or pdata) */ struct hdmi_platform_config { - /* regulators that need to be on for hpd: */ - const char **hpd_reg_names; - int hpd_reg_cnt; - /* regulators that need to be on for screen pwr: */ - const char **pwr_reg_names; + const char * const *pwr_reg_names; int pwr_reg_cnt; - /* clks that need to be on for hpd: */ - const char **hpd_clk_names; - const long unsigned *hpd_freq; - int hpd_clk_cnt; - - /* clks that need to be on for screen pwr (ie pixel clk): */ - const char **pwr_clk_names; + /* clks that need to be on: */ + const char * const *pwr_clk_names; int pwr_clk_cnt; }; @@ -207,26 +196,16 @@ static inline int msm_hdmi_pll_8998_init(struct platform_device *pdev) /* * audio: */ -/* Supported HDMI Audio channels and rates */ -#define MSM_HDMI_AUDIO_CHANNEL_2 0 -#define MSM_HDMI_AUDIO_CHANNEL_4 1 -#define MSM_HDMI_AUDIO_CHANNEL_6 2 -#define MSM_HDMI_AUDIO_CHANNEL_8 3 - -#define HDMI_SAMPLE_RATE_32KHZ 0 -#define HDMI_SAMPLE_RATE_44_1KHZ 1 -#define HDMI_SAMPLE_RATE_48KHZ 2 -#define HDMI_SAMPLE_RATE_88_2KHZ 3 -#define HDMI_SAMPLE_RATE_96KHZ 4 -#define HDMI_SAMPLE_RATE_176_4KHZ 5 -#define HDMI_SAMPLE_RATE_192KHZ 6 +struct hdmi_codec_daifmt; +struct hdmi_codec_params; int msm_hdmi_audio_update(struct hdmi *hdmi); -int msm_hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled, - uint32_t num_of_channels, uint32_t channel_allocation, - uint32_t level_shift, bool down_mix); -void msm_hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate); - +int msm_hdmi_bridge_audio_prepare(struct drm_bridge *bridge, + struct drm_connector *connector, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params); +void msm_hdmi_bridge_audio_shutdown(struct drm_bridge *bridge, + struct drm_connector *connector); /* * hdmi bridge: @@ -236,9 +215,9 @@ 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 *hdmi); + struct drm_bridge *bridge, struct drm_connector *connector); +void msm_hdmi_hpd_enable(struct drm_bridge *bridge); +void msm_hdmi_hpd_disable(struct drm_bridge *bridge); /* * i2c adapter for ddc: diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c index 4c2058c4adc1..d9a8dc9dae8f 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c @@ -4,86 +4,28 @@ * Author: Rob Clark <robdclark@gmail.com> */ -#include <linux/hdmi.h> -#include "hdmi.h" +#include <drm/display/drm_hdmi_helper.h> +#include <drm/display/drm_hdmi_state_helper.h> -/* maps MSM_HDMI_AUDIO_CHANNEL_n consts used by audio driver to # of channels: */ -static int nchannels[] = { 2, 4, 6, 8 }; - -/* Supported HDMI Audio sample rates */ -#define MSM_HDMI_SAMPLE_RATE_32KHZ 0 -#define MSM_HDMI_SAMPLE_RATE_44_1KHZ 1 -#define MSM_HDMI_SAMPLE_RATE_48KHZ 2 -#define MSM_HDMI_SAMPLE_RATE_88_2KHZ 3 -#define MSM_HDMI_SAMPLE_RATE_96KHZ 4 -#define MSM_HDMI_SAMPLE_RATE_176_4KHZ 5 -#define MSM_HDMI_SAMPLE_RATE_192KHZ 6 -#define MSM_HDMI_SAMPLE_RATE_MAX 7 - - -struct hdmi_msm_audio_acr { - uint32_t n; /* N parameter for clock regeneration */ - uint32_t cts; /* CTS parameter for clock regeneration */ -}; - -struct hdmi_msm_audio_arcs { - unsigned long int pixclock; - struct hdmi_msm_audio_acr lut[MSM_HDMI_SAMPLE_RATE_MAX]; -}; - -#define HDMI_MSM_AUDIO_ARCS(pclk, ...) { (1000 * (pclk)), __VA_ARGS__ } - -/* Audio constants lookup table for hdmi_msm_audio_acr_setup */ -/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */ -static const struct hdmi_msm_audio_arcs acr_lut[] = { - /* 25.200MHz */ - HDMI_MSM_AUDIO_ARCS(25200, { - {4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000}, - {12288, 25200}, {25088, 28000}, {24576, 25200} }), - /* 27.000MHz */ - HDMI_MSM_AUDIO_ARCS(27000, { - {4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000}, - {12288, 27000}, {25088, 30000}, {24576, 27000} }), - /* 27.027MHz */ - HDMI_MSM_AUDIO_ARCS(27030, { - {4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030}, - {12288, 27027}, {25088, 30030}, {24576, 27027} }), - /* 74.250MHz */ - HDMI_MSM_AUDIO_ARCS(74250, { - {4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500}, - {12288, 74250}, {25088, 82500}, {24576, 74250} }), - /* 148.500MHz */ - HDMI_MSM_AUDIO_ARCS(148500, { - {4096, 148500}, {6272, 165000}, {6144, 148500}, {12544, 165000}, - {12288, 148500}, {25088, 165000}, {24576, 148500} }), -}; - -static const struct hdmi_msm_audio_arcs *get_arcs(unsigned long int pixclock) -{ - int i; +#include <linux/hdmi.h> - for (i = 0; i < ARRAY_SIZE(acr_lut); i++) { - const struct hdmi_msm_audio_arcs *arcs = &acr_lut[i]; - if (arcs->pixclock == pixclock) - return arcs; - } +#include <sound/hdmi-codec.h> - return NULL; -} +#include "hdmi.h" int msm_hdmi_audio_update(struct hdmi *hdmi) { struct hdmi_audio *audio = &hdmi->audio; - struct hdmi_audio_infoframe *info = &audio->infoframe; - const struct hdmi_msm_audio_arcs *arcs = NULL; bool enabled = audio->enabled; uint32_t acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl; - uint32_t infofrm_ctrl, audio_config; + uint32_t audio_config; + + if (!hdmi->connector->display_info.is_hdmi) + return -EINVAL; + + DBG("audio: enabled=%d, channels=%d, rate=%d", + audio->enabled, audio->channels, audio->rate); - DBG("audio: enabled=%d, channels=%d, channel_allocation=0x%x, " - "level_shift_value=%d, downmix_inhibit=%d, rate=%d", - audio->enabled, info->channels, info->channel_allocation, - info->level_shift_value, info->downmix_inhibit, audio->rate); DBG("video: power_on=%d, pixclock=%lu", hdmi->power_on, hdmi->pixclock); if (enabled && !(hdmi->power_on && hdmi->pixclock)) { @@ -91,20 +33,10 @@ int msm_hdmi_audio_update(struct hdmi *hdmi) enabled = false; } - if (enabled) { - arcs = get_arcs(hdmi->pixclock); - if (!arcs) { - DBG("disabling audio: unsupported pixclock: %lu", - hdmi->pixclock); - enabled = false; - } - } - /* Read first before writing */ acr_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_ACR_PKT_CTRL); vbi_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_VBI_PKT_CTRL); aud_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_AUDIO_PKT_CTRL1); - infofrm_ctrl = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); audio_config = hdmi_read(hdmi, REG_HDMI_AUDIO_CFG); /* Clear N/CTS selection bits */ @@ -113,17 +45,13 @@ int msm_hdmi_audio_update(struct hdmi *hdmi) if (enabled) { uint32_t n, cts, multiplier; enum hdmi_acr_cts select; - uint8_t buf[14]; - n = arcs->lut[audio->rate].n; - cts = arcs->lut[audio->rate].cts; + drm_hdmi_acr_get_n_cts(hdmi->pixclock, audio->rate, &n, &cts); - if ((MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate)) { + if (audio->rate == 192000 || audio->rate == 176400) { multiplier = 4; n >>= 2; /* divide N by 4 and use multiplier */ - } else if ((MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate)) { + } else if (audio->rate == 96000 || audio->rate == 88200) { multiplier = 2; n >>= 1; /* divide N by 2 and use multiplier */ } else { @@ -136,13 +64,11 @@ int msm_hdmi_audio_update(struct hdmi *hdmi) acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_AUDIO_PRIORITY; acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_N_MULTIPLIER(multiplier); - if ((MSM_HDMI_SAMPLE_RATE_48KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate)) + if (audio->rate == 48000 || audio->rate == 96000 || + audio->rate == 192000) select = ACR_48; - else if ((MSM_HDMI_SAMPLE_RATE_44_1KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate) || - (MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate)) + else if (audio->rate == 44100 || audio->rate == 88200 || + audio->rate == 176400) select = ACR_44; else /* default to 32k */ select = ACR_32; @@ -155,20 +81,12 @@ int msm_hdmi_audio_update(struct hdmi *hdmi) HDMI_ACR_1_N(n)); hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL2, - COND(info->channels != 2, HDMI_AUDIO_PKT_CTRL2_LAYOUT) | + COND(audio->channels != 2, HDMI_AUDIO_PKT_CTRL2_LAYOUT) | HDMI_AUDIO_PKT_CTRL2_OVERRIDE); acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_CONT; acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SEND; - /* configure infoframe: */ - hdmi_audio_infoframe_pack(info, buf, sizeof(buf)); - hdmi_write(hdmi, REG_HDMI_AUDIO_INFO0, - (buf[3] << 0) | (buf[4] << 8) | - (buf[5] << 16) | (buf[6] << 24)); - hdmi_write(hdmi, REG_HDMI_AUDIO_INFO1, - (buf[7] << 0) | (buf[8] << 8)); - hdmi_write(hdmi, REG_HDMI_GC, 0); vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_ENABLE; @@ -176,11 +94,6 @@ int msm_hdmi_audio_update(struct hdmi *hdmi) aud_pkt_ctrl |= HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND; - infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND; - infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT; - infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE; - infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE; - audio_config &= ~HDMI_AUDIO_CFG_FIFO_WATERMARK__MASK; audio_config |= HDMI_AUDIO_CFG_FIFO_WATERMARK(4); audio_config |= HDMI_AUDIO_CFG_ENGINE_ENABLE; @@ -190,17 +103,12 @@ int msm_hdmi_audio_update(struct hdmi *hdmi) vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_ENABLE; vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME; aud_pkt_ctrl &= ~HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND; - infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND; - infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT; - infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE; - infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE; audio_config &= ~HDMI_AUDIO_CFG_ENGINE_ENABLE; } hdmi_write(hdmi, REG_HDMI_ACR_PKT_CTRL, acr_pkt_ctrl); hdmi_write(hdmi, REG_HDMI_VBI_PKT_CTRL, vbi_pkt_ctrl); hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL1, aud_pkt_ctrl); - hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, infofrm_ctrl); hdmi_write(hdmi, REG_HDMI_AUD_INT, COND(enabled, HDMI_AUD_INT_AUD_FIFO_URUN_INT) | @@ -214,41 +122,58 @@ int msm_hdmi_audio_update(struct hdmi *hdmi) return 0; } -int msm_hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled, - uint32_t num_of_channels, uint32_t channel_allocation, - uint32_t level_shift, bool down_mix) +int msm_hdmi_bridge_audio_prepare(struct drm_bridge *bridge, + struct drm_connector *connector, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params) { - struct hdmi_audio *audio; - - if (!hdmi) - return -ENXIO; - - audio = &hdmi->audio; - - if (num_of_channels >= ARRAY_SIZE(nchannels)) + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = hdmi_bridge->hdmi; + int ret; + + drm_dbg_driver(bridge->dev, "%u Hz, %d bit, %d channels\n", + params->sample_rate, + params->sample_width, + params->cea.channels); + + switch (params->sample_rate) { + case 32000: + case 44100: + case 48000: + case 88200: + case 96000: + case 176400: + case 192000: + break; + default: + drm_err(bridge->dev, "rate[%d] not supported!\n", + params->sample_rate); return -EINVAL; + } - audio->enabled = enabled; - audio->infoframe.channels = nchannels[num_of_channels]; - audio->infoframe.channel_allocation = channel_allocation; - audio->infoframe.level_shift_value = level_shift; - audio->infoframe.downmix_inhibit = down_mix; + ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, + ¶ms->cea); + if (ret) + return ret; + + hdmi->audio.rate = params->sample_rate; + hdmi->audio.channels = params->cea.channels; + hdmi->audio.enabled = true; return msm_hdmi_audio_update(hdmi); } -void msm_hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate) +void msm_hdmi_bridge_audio_shutdown(struct drm_bridge *bridge, + struct drm_connector *connector) { - struct hdmi_audio *audio; - - if (!hdmi) - return; + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = hdmi_bridge->hdmi; - audio = &hdmi->audio; + drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector); - if ((rate < 0) || (rate >= MSM_HDMI_SAMPLE_RATE_MAX)) - return; + hdmi->audio.rate = 0; + hdmi->audio.channels = 2; + hdmi->audio.enabled = false; - audio->rate = rate; msm_hdmi_audio_update(hdmi); } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 4a5b5112227f..46fd58646d32 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -7,6 +7,8 @@ #include <linux/delay.h> #include <drm/drm_bridge_connector.h> #include <drm/drm_edid.h> +#include <drm/display/drm_hdmi_helper.h> +#include <drm/display/drm_hdmi_state_helper.h> #include "msm_kms.h" #include "hdmi.h" @@ -16,75 +18,53 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) struct drm_device *dev = bridge->dev; struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - const struct hdmi_platform_config *config = hdmi->config; - int i, ret; - - pm_runtime_get_sync(&hdmi->pdev->dev); + int ret; - ret = regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs); - if (ret) - DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %d\n", ret); + pm_runtime_resume_and_get(&hdmi->pdev->dev); - if (config->pwr_clk_cnt > 0) { + if (hdmi->extp_clk) { DBG("pixclock: %lu", hdmi->pixclock); - ret = clk_set_rate(hdmi->pwr_clks[0], hdmi->pixclock); - if (ret) { - DRM_DEV_ERROR(dev->dev, "failed to set pixel clk: %s (%d)\n", - config->pwr_clk_names[0], ret); - } - } + ret = clk_set_rate(hdmi->extp_clk, hdmi->pixclock); + if (ret) + DRM_DEV_ERROR(dev->dev, "failed to set extp clk rate: %d\n", ret); - for (i = 0; i < config->pwr_clk_cnt; i++) { - ret = clk_prepare_enable(hdmi->pwr_clks[i]); - if (ret) { - DRM_DEV_ERROR(dev->dev, "failed to enable pwr clk: %s (%d)\n", - config->pwr_clk_names[i], ret); - } + ret = clk_prepare_enable(hdmi->extp_clk); + if (ret) + DRM_DEV_ERROR(dev->dev, "failed to enable extp clk: %d\n", ret); } } static void power_off(struct drm_bridge *bridge) { - struct drm_device *dev = bridge->dev; struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - const struct hdmi_platform_config *config = hdmi->config; - int i, ret; /* TODO do we need to wait for final vblank somewhere before * cutting the clocks? */ mdelay(16 + 4); - for (i = 0; i < config->pwr_clk_cnt; i++) - clk_disable_unprepare(hdmi->pwr_clks[i]); - - ret = regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs); - if (ret) - DRM_DEV_ERROR(dev->dev, "failed to disable pwr regulator: %d\n", ret); + if (hdmi->extp_clk) + clk_disable_unprepare(hdmi->extp_clk); pm_runtime_put(&hdmi->pdev->dev); } #define AVI_IFRAME_LINE_NUMBER 1 +#define SPD_IFRAME_LINE_NUMBER 1 +#define VENSPEC_IFRAME_LINE_NUMBER 3 -static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi) +static int msm_hdmi_config_avi_infoframe(struct hdmi *hdmi, + const u8 *buffer, size_t len) { - struct drm_crtc *crtc = hdmi->encoder->crtc; - const struct drm_display_mode *mode = &crtc->state->adjusted_mode; - union hdmi_infoframe frame; - u8 buffer[HDMI_INFOFRAME_SIZE(AVI)]; + u32 buf[4] = {}; u32 val; - int len; - - drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, - hdmi->connector, mode); + int i; - len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer)); - if (len < 0) { + if (len != HDMI_INFOFRAME_SIZE(AVI) || len - 3 > sizeof(buf)) { DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to configure avi infoframe\n"); - return; + return -EINVAL; } /* @@ -93,56 +73,247 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi) * written to the LSB byte of AVI_INFO0 and the version is written to * the third byte from the LSB of AVI_INFO3 */ - hdmi_write(hdmi, REG_HDMI_AVI_INFO(0), + memcpy(buf, &buffer[3], len - 3); + + buf[3] |= buffer[1] << 24; + + for (i = 0; i < ARRAY_SIZE(buf); i++) + hdmi_write(hdmi, REG_HDMI_AVI_INFO(i), buf[i]); + + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); + val |= HDMI_INFOFRAME_CTRL0_AVI_SEND | + HDMI_INFOFRAME_CTRL0_AVI_CONT; + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); + + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); + val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK; + val |= HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER); + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); + + return 0; +} + +static int msm_hdmi_config_audio_infoframe(struct hdmi *hdmi, + const u8 *buffer, size_t len) +{ + u32 val; + + if (len != HDMI_INFOFRAME_SIZE(AUDIO)) { + DRM_DEV_ERROR(&hdmi->pdev->dev, + "failed to configure audio infoframe\n"); + return -EINVAL; + } + + hdmi_write(hdmi, REG_HDMI_AUDIO_INFO0, buffer[3] | buffer[4] << 8 | buffer[5] << 16 | buffer[6] << 24); - hdmi_write(hdmi, REG_HDMI_AVI_INFO(1), + hdmi_write(hdmi, REG_HDMI_AUDIO_INFO1, buffer[7] | buffer[8] << 8 | buffer[9] << 16 | buffer[10] << 24); - hdmi_write(hdmi, REG_HDMI_AVI_INFO(2), - buffer[11] | - buffer[12] << 8 | - buffer[13] << 16 | - buffer[14] << 24); + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); + val |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE; + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); - hdmi_write(hdmi, REG_HDMI_AVI_INFO(3), - buffer[15] | - buffer[16] << 8 | - buffer[1] << 24); + return 0; +} - hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, - HDMI_INFOFRAME_CTRL0_AVI_SEND | - HDMI_INFOFRAME_CTRL0_AVI_CONT); +static int msm_hdmi_config_spd_infoframe(struct hdmi *hdmi, + const u8 *buffer, size_t len) +{ + u32 buf[7] = {}; + u32 val; + int i; - val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); - val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK; - val |= HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER); - hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); + if (len != HDMI_INFOFRAME_SIZE(SPD) || len - 3 > sizeof(buf)) { + DRM_DEV_ERROR(&hdmi->pdev->dev, + "failed to configure SPD infoframe\n"); + return -EINVAL; + } + + /* checksum gets written together with the body of the frame */ + hdmi_write(hdmi, REG_HDMI_GENERIC1_HDR, + buffer[0] | + buffer[1] << 8 | + buffer[2] << 16); + + memcpy(buf, &buffer[3], len - 3); + + for (i = 0; i < ARRAY_SIZE(buf); i++) + hdmi_write(hdmi, REG_HDMI_GENERIC1(i), buf[i]); + + val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); + val |= HDMI_GEN_PKT_CTRL_GENERIC1_SEND | + HDMI_GEN_PKT_CTRL_GENERIC1_CONT | + HDMI_GEN_PKT_CTRL_GENERIC1_LINE(SPD_IFRAME_LINE_NUMBER); + hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); + + return 0; } -static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge) +static int msm_hdmi_config_hdmi_infoframe(struct hdmi *hdmi, + const u8 *buffer, size_t len) +{ + u32 buf[7] = {}; + u32 val; + int i; + + if (len < HDMI_INFOFRAME_HEADER_SIZE + HDMI_VENDOR_INFOFRAME_SIZE || + len - 3 > sizeof(buf)) { + DRM_DEV_ERROR(&hdmi->pdev->dev, + "failed to configure HDMI infoframe\n"); + return -EINVAL; + } + + /* checksum gets written together with the body of the frame */ + hdmi_write(hdmi, REG_HDMI_GENERIC0_HDR, + buffer[0] | + buffer[1] << 8 | + buffer[2] << 16); + + memcpy(buf, &buffer[3], len - 3); + + for (i = 0; i < ARRAY_SIZE(buf); i++) + hdmi_write(hdmi, REG_HDMI_GENERIC0(i), buf[i]); + + val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); + val |= HDMI_GEN_PKT_CTRL_GENERIC0_SEND | + HDMI_GEN_PKT_CTRL_GENERIC0_CONT | + HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | + HDMI_GEN_PKT_CTRL_GENERIC0_LINE(VENSPEC_IFRAME_LINE_NUMBER); + hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); + + return 0; +} + +static int msm_hdmi_bridge_clear_infoframe(struct drm_bridge *bridge, + enum hdmi_infoframe_type type) +{ + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = hdmi_bridge->hdmi; + u32 val; + + switch (type) { + case HDMI_INFOFRAME_TYPE_AVI: + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); + val &= ~(HDMI_INFOFRAME_CTRL0_AVI_SEND | + HDMI_INFOFRAME_CTRL0_AVI_CONT); + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); + + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); + val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK; + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); + + break; + + case HDMI_INFOFRAME_TYPE_AUDIO: + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); + val &= ~(HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | + HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE); + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); + + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); + val &= ~HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__MASK; + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); + + break; + + case HDMI_INFOFRAME_TYPE_SPD: + val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); + val &= ~(HDMI_GEN_PKT_CTRL_GENERIC1_SEND | + HDMI_GEN_PKT_CTRL_GENERIC1_CONT | + HDMI_GEN_PKT_CTRL_GENERIC1_LINE__MASK); + hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); + + break; + + case HDMI_INFOFRAME_TYPE_VENDOR: + val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); + val &= ~(HDMI_GEN_PKT_CTRL_GENERIC0_SEND | + HDMI_GEN_PKT_CTRL_GENERIC0_CONT | + HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE | + HDMI_GEN_PKT_CTRL_GENERIC0_LINE__MASK); + hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val); + + break; + + default: + drm_dbg_driver(hdmi_bridge->base.dev, "Unsupported infoframe type %x\n", type); + } + + return 0; +} + +static int msm_hdmi_bridge_write_infoframe(struct drm_bridge *bridge, + enum hdmi_infoframe_type type, + const u8 *buffer, size_t len) +{ + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = hdmi_bridge->hdmi; + + msm_hdmi_bridge_clear_infoframe(bridge, type); + + switch (type) { + case HDMI_INFOFRAME_TYPE_AVI: + return msm_hdmi_config_avi_infoframe(hdmi, buffer, len); + case HDMI_INFOFRAME_TYPE_AUDIO: + return msm_hdmi_config_audio_infoframe(hdmi, buffer, len); + case HDMI_INFOFRAME_TYPE_SPD: + return msm_hdmi_config_spd_infoframe(hdmi, buffer, len); + case HDMI_INFOFRAME_TYPE_VENDOR: + return msm_hdmi_config_hdmi_infoframe(hdmi, buffer, len); + default: + drm_dbg_driver(hdmi_bridge->base.dev, "Unsupported infoframe type %x\n", type); + return 0; + } +} + +static void msm_hdmi_set_timings(struct hdmi *hdmi, + const struct drm_display_mode *mode); + +static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; struct hdmi_phy *phy = hdmi->phy; + struct drm_encoder *encoder = bridge->encoder; + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; DBG("power up"); + connector = drm_atomic_get_new_connector_for_encoder(state, encoder); + conn_state = drm_atomic_get_new_connector_state(state, connector); + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + + hdmi->pixclock = conn_state->hdmi.tmds_char_rate; + + msm_hdmi_set_timings(hdmi, &crtc_state->adjusted_mode); + + mutex_lock(&hdmi->state_mutex); if (!hdmi->power_on) { msm_hdmi_phy_resource_enable(phy); msm_hdmi_power_on(bridge); hdmi->power_on = true; - if (hdmi->hdmi_mode) { - msm_hdmi_config_avi_infoframe(hdmi); - msm_hdmi_audio_update(hdmi); - } } + mutex_unlock(&hdmi->state_mutex); + + if (connector->display_info.is_hdmi) + msm_hdmi_audio_update(hdmi); + + drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); msm_hdmi_phy_powerup(phy, hdmi->pixclock); @@ -152,7 +323,8 @@ static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge) msm_hdmi_hdcp_on(hdmi->hdcp_ctrl); } -static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge) +static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; @@ -162,32 +334,29 @@ static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge) msm_hdmi_hdcp_off(hdmi->hdcp_ctrl); DBG("power down"); - msm_hdmi_set_mode(hdmi, false); + + /* Keep the HDMI enabled if the HPD is enabled */ + mutex_lock(&hdmi->state_mutex); + msm_hdmi_set_mode(hdmi, hdmi->hpd_enabled); msm_hdmi_phy_powerdown(phy); if (hdmi->power_on) { power_off(bridge); hdmi->power_on = false; - if (hdmi->hdmi_mode) + if (hdmi->connector->display_info.is_hdmi) msm_hdmi_audio_update(hdmi); msm_hdmi_phy_resource_disable(phy); } + mutex_unlock(&hdmi->state_mutex); } -static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adjusted_mode) +static void msm_hdmi_set_timings(struct hdmi *hdmi, + const struct drm_display_mode *mode) { - struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); - struct hdmi *hdmi = hdmi_bridge->hdmi; int hstart, hend, vstart, vend; uint32_t frame_ctrl; - mode = adjusted_mode; - - hdmi->pixclock = mode->clock * 1000; - hstart = mode->htotal - mode->hsync_start; hend = mode->htotal - mode->hsync_start + mode->hdisplay; @@ -231,9 +400,6 @@ static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge, frame_ctrl |= HDMI_FRAME_CTRL_INTERLACED_EN; DBG("frame_ctrl=%08x", frame_ctrl); hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl); - - if (hdmi->hdmi_mode) - msm_hdmi_audio_update(hdmi); } static const struct drm_edid *msm_hdmi_bridge_edid_read(struct drm_bridge *bridge, @@ -251,32 +417,18 @@ static const struct drm_edid *msm_hdmi_bridge_edid_read(struct drm_bridge *bridg hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl); - if (drm_edid) { - /* - * FIXME: This should use connector->display_info.is_hdmi from a - * path that has read the EDID and called - * drm_edid_connector_update(). - */ - const struct edid *edid = drm_edid_raw(drm_edid); - - hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid); - } - return drm_edid; } -static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge, - const struct drm_display_info *info, - const struct drm_display_mode *mode) +static enum drm_mode_status msm_hdmi_bridge_tmds_char_rate_valid(const struct drm_bridge *bridge, + const struct drm_display_mode *mode, + unsigned long long tmds_rate) { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - const struct hdmi_platform_config *config = hdmi->config; struct msm_drm_private *priv = bridge->dev->dev_private; struct msm_kms *kms = priv->kms; - long actual, requested; - - requested = 1000 * mode->clock; + long actual; /* for mdp5/apq8074, we manage our own pixel clk (as opposed to * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder @@ -284,27 +436,36 @@ static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge */ if (kms->funcs->round_pixclk) actual = kms->funcs->round_pixclk(kms, - requested, hdmi_bridge->hdmi->encoder); - else if (config->pwr_clk_cnt > 0) - actual = clk_round_rate(hdmi->pwr_clks[0], requested); + tmds_rate, + hdmi_bridge->hdmi->encoder); + else if (hdmi->extp_clk) + actual = clk_round_rate(hdmi->extp_clk, tmds_rate); else - actual = requested; + actual = tmds_rate; - DBG("requested=%ld, actual=%ld", requested, actual); + DBG("requested=%lld, actual=%ld", tmds_rate, actual); - if (actual != requested) + if (actual != tmds_rate) return MODE_CLOCK_RANGE; return 0; } static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = { - .pre_enable = msm_hdmi_bridge_pre_enable, - .post_disable = msm_hdmi_bridge_post_disable, - .mode_set = msm_hdmi_bridge_mode_set, - .mode_valid = msm_hdmi_bridge_mode_valid, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_pre_enable = msm_hdmi_bridge_atomic_pre_enable, + .atomic_post_disable = msm_hdmi_bridge_atomic_post_disable, .edid_read = msm_hdmi_bridge_edid_read, .detect = msm_hdmi_bridge_detect, + .hpd_enable = msm_hdmi_hpd_enable, + .hpd_disable = msm_hdmi_hpd_disable, + .hdmi_tmds_char_rate_valid = msm_hdmi_bridge_tmds_char_rate_valid, + .hdmi_clear_infoframe = msm_hdmi_bridge_clear_infoframe, + .hdmi_write_infoframe = msm_hdmi_bridge_write_infoframe, + .hdmi_audio_prepare = msm_hdmi_bridge_audio_prepare, + .hdmi_audio_shutdown = msm_hdmi_bridge_audio_shutdown, }; static void @@ -314,7 +475,7 @@ msm_hdmi_hotplug_work(struct work_struct *work) container_of(work, struct hdmi_bridge, hpd_work); struct drm_bridge *bridge = &hdmi_bridge->base; - drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge)); + drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge, hdmi_bridge->hdmi->connector)); } /* initialize bridge */ @@ -324,21 +485,27 @@ int msm_hdmi_bridge_init(struct hdmi *hdmi) struct hdmi_bridge *hdmi_bridge; int ret; - hdmi_bridge = devm_kzalloc(hdmi->dev->dev, - sizeof(*hdmi_bridge), GFP_KERNEL); - if (!hdmi_bridge) - return -ENOMEM; + hdmi_bridge = devm_drm_bridge_alloc(hdmi->dev->dev, struct hdmi_bridge, base, + &msm_hdmi_bridge_funcs); + if (IS_ERR(hdmi_bridge)) + return PTR_ERR(hdmi_bridge); hdmi_bridge->hdmi = hdmi; INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work); bridge = &hdmi_bridge->base; - bridge->funcs = &msm_hdmi_bridge_funcs; bridge->ddc = hdmi->i2c; bridge->type = DRM_MODE_CONNECTOR_HDMIA; + bridge->vendor = "Qualcomm"; + bridge->product = "Snapdragon"; bridge->ops = DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_DETECT | + DRM_BRIDGE_OP_HDMI | + DRM_BRIDGE_OP_HDMI_AUDIO | DRM_BRIDGE_OP_EDID; + bridge->hdmi_audio_max_i2s_playback_channels = 8; + bridge->hdmi_audio_dev = &hdmi->pdev->dev; + bridge->hdmi_audio_dai_port = -1; ret = devm_drm_bridge_add(hdmi->dev->dev, bridge); if (ret) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c index 9ce0ffa35417..114b0d507700 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c @@ -60,68 +60,30 @@ static void msm_hdmi_phy_reset(struct hdmi *hdmi) } } -static void enable_hpd_clocks(struct hdmi *hdmi, bool enable) -{ - const struct hdmi_platform_config *config = hdmi->config; - struct device *dev = &hdmi->pdev->dev; - int i, ret; - - if (enable) { - for (i = 0; i < config->hpd_clk_cnt; i++) { - if (config->hpd_freq && config->hpd_freq[i]) { - ret = clk_set_rate(hdmi->hpd_clks[i], - config->hpd_freq[i]); - if (ret) - dev_warn(dev, - "failed to set clk %s (%d)\n", - config->hpd_clk_names[i], ret); - } - - ret = clk_prepare_enable(hdmi->hpd_clks[i]); - if (ret) { - DRM_DEV_ERROR(dev, - "failed to enable hpd clk: %s (%d)\n", - config->hpd_clk_names[i], ret); - } - } - } else { - for (i = config->hpd_clk_cnt - 1; i >= 0; i--) - clk_disable_unprepare(hdmi->hpd_clks[i]); - } -} - -int msm_hdmi_hpd_enable(struct drm_bridge *bridge) +void msm_hdmi_hpd_enable(struct drm_bridge *bridge) { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - const struct hdmi_platform_config *config = hdmi->config; struct device *dev = &hdmi->pdev->dev; uint32_t hpd_ctrl; int ret; unsigned long flags; - ret = regulator_bulk_enable(config->hpd_reg_cnt, hdmi->hpd_regs); - if (ret) { - DRM_DEV_ERROR(dev, "failed to enable hpd regulators: %d\n", ret); - goto fail; - } - - ret = pinctrl_pm_select_default_state(dev); - if (ret) { - DRM_DEV_ERROR(dev, "pinctrl state chg failed: %d\n", ret); - goto fail; - } - if (hdmi->hpd_gpiod) gpiod_set_value_cansleep(hdmi->hpd_gpiod, 1); - pm_runtime_get_sync(dev); - enable_hpd_clocks(hdmi, true); + ret = pm_runtime_resume_and_get(dev); + if (WARN_ON(ret)) + return; + mutex_lock(&hdmi->state_mutex); msm_hdmi_set_mode(hdmi, false); msm_hdmi_phy_reset(hdmi); msm_hdmi_set_mode(hdmi, true); + hdmi->hpd_enabled = true; + mutex_unlock(&hdmi->state_mutex); + hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b); /* enable HPD events: */ @@ -140,34 +102,23 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge) hdmi_write(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE | hpd_ctrl); spin_unlock_irqrestore(&hdmi->reg_lock, flags); - - return 0; - -fail: - return ret; } -void msm_hdmi_hpd_disable(struct hdmi *hdmi) +void msm_hdmi_hpd_disable(struct drm_bridge *bridge) { - const struct hdmi_platform_config *config = hdmi->config; + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = hdmi_bridge->hdmi; struct device *dev = &hdmi->pdev->dev; - int ret; /* Disable HPD interrupt */ hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0); - msm_hdmi_set_mode(hdmi, false); + mutex_lock(&hdmi->state_mutex); + hdmi->hpd_enabled = false; + msm_hdmi_set_mode(hdmi, hdmi->power_on); + mutex_unlock(&hdmi->state_mutex); - enable_hpd_clocks(hdmi, false); pm_runtime_put(dev); - - ret = pinctrl_pm_select_sleep_state(dev); - if (ret) - dev_warn(dev, "pinctrl state chg failed: %d\n", ret); - - ret = regulator_bulk_disable(config->hpd_reg_cnt, hdmi->hpd_regs); - if (ret) - dev_warn(dev, "failed to disable hpd regulator: %d\n", ret); } void msm_hdmi_hpd_irq(struct drm_bridge *bridge) @@ -202,14 +153,16 @@ void msm_hdmi_hpd_irq(struct drm_bridge *bridge) static enum drm_connector_status detect_reg(struct hdmi *hdmi) { - uint32_t hpd_int_status; + u32 hpd_int_status = 0; + int ret; - pm_runtime_get_sync(&hdmi->pdev->dev); - enable_hpd_clocks(hdmi, true); + ret = pm_runtime_resume_and_get(&hdmi->pdev->dev); + if (ret) + goto out; hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS); - enable_hpd_clocks(hdmi, false); +out: pm_runtime_put(&hdmi->pdev->dev); return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ? @@ -224,8 +177,8 @@ static enum drm_connector_status detect_gpio(struct hdmi *hdmi) connector_status_disconnected; } -enum drm_connector_status msm_hdmi_bridge_detect( - struct drm_bridge *bridge) +enum drm_connector_status +msm_hdmi_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector) { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c b/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c index 7aa500d24240..ebefea4fb408 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c @@ -107,11 +107,15 @@ static int msm_hdmi_i2c_xfer(struct i2c_adapter *i2c, if (num == 0) return num; + ret = pm_runtime_resume_and_get(&hdmi->pdev->dev); + if (ret) + return ret; + init_ddc(hdmi_i2c); ret = ddc_clear_irq(hdmi_i2c); if (ret) - return ret; + goto fail; for (i = 0; i < num; i++) { struct i2c_msg *p = &msgs[i]; @@ -169,7 +173,7 @@ static int msm_hdmi_i2c_xfer(struct i2c_adapter *i2c, hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS), hdmi_read(hdmi, REG_HDMI_DDC_HW_STATUS), hdmi_read(hdmi, REG_HDMI_DDC_INT_CTRL)); - return ret; + goto fail; } ddc_status = hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS); @@ -202,7 +206,13 @@ static int msm_hdmi_i2c_xfer(struct i2c_adapter *i2c, } } + pm_runtime_put(&hdmi->pdev->dev); + return i; + +fail: + pm_runtime_put(&hdmi->pdev->dev); + return ret; } static u32 msm_hdmi_i2c_func(struct i2c_adapter *adapter) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c index 95b3f7535d84..667573f1db7c 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c @@ -58,7 +58,11 @@ int msm_hdmi_phy_resource_enable(struct hdmi_phy *phy) struct device *dev = &phy->pdev->dev; int i, ret = 0; - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) { + DRM_DEV_ERROR(dev, "runtime resume failed: %d\n", ret); + return ret; + } ret = regulator_bulk_enable(cfg->num_regs, phy->regs); if (ret) { @@ -203,7 +207,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_new = msm_hdmi_phy_remove, + .remove = msm_hdmi_phy_remove, .driver = { .name = "msm_hdmi_phy", .of_match_table = msm_hdmi_phy_dt_match, diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c index 8c8d80b59573..36e928b0fd5a 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c @@ -629,16 +629,12 @@ static int hdmi_8996_pll_prepare(struct clk_hw *hw) return 0; } -static long hdmi_8996_pll_round_rate(struct clk_hw *hw, - unsigned long rate, - unsigned long *parent_rate) +static int hdmi_8996_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - if (rate < HDMI_PCLK_MIN_FREQ) - return HDMI_PCLK_MIN_FREQ; - else if (rate > HDMI_PCLK_MAX_FREQ) - return HDMI_PCLK_MAX_FREQ; - else - return rate; + req->rate = clamp_t(unsigned long, req->rate, HDMI_PCLK_MIN_FREQ, HDMI_PCLK_MAX_FREQ); + + return 0; } static unsigned long hdmi_8996_pll_recalc_rate(struct clk_hw *hw, @@ -684,7 +680,7 @@ static int hdmi_8996_pll_is_enabled(struct clk_hw *hw) static const struct clk_ops hdmi_8996_pll_ops = { .set_rate = hdmi_8996_pll_set_clk_rate, - .round_rate = hdmi_8996_pll_round_rate, + .determine_rate = hdmi_8996_pll_determine_rate, .recalc_rate = hdmi_8996_pll_recalc_rate, .prepare = hdmi_8996_pll_prepare, .unprepare = hdmi_8996_pll_unprepare, diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c index a719fd33d9d8..a86ff3706369 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c @@ -137,7 +137,7 @@ static inline u32 pll_get_integloop_gain(u64 frac_start, u64 bclk, u32 ref_clk, base <<= (digclk_divsel == 2 ? 1 : 0); - return (base <= 2046 ? base : 2046); + return base; } static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk) @@ -646,16 +646,12 @@ static int hdmi_8998_pll_prepare(struct clk_hw *hw) return 0; } -static long hdmi_8998_pll_round_rate(struct clk_hw *hw, - unsigned long rate, - unsigned long *parent_rate) +static int hdmi_8998_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - if (rate < HDMI_PCLK_MIN_FREQ) - return HDMI_PCLK_MIN_FREQ; - else if (rate > HDMI_PCLK_MAX_FREQ) - return HDMI_PCLK_MAX_FREQ; - else - return rate; + req->rate = clamp_t(unsigned long, req->rate, HDMI_PCLK_MIN_FREQ, HDMI_PCLK_MAX_FREQ); + + return 0; } static unsigned long hdmi_8998_pll_recalc_rate(struct clk_hw *hw, @@ -688,7 +684,7 @@ static int hdmi_8998_pll_is_enabled(struct clk_hw *hw) static const struct clk_ops hdmi_8998_pll_ops = { .set_rate = hdmi_8998_pll_set_clk_rate, - .round_rate = hdmi_8998_pll_round_rate, + .determine_rate = hdmi_8998_pll_determine_rate, .recalc_rate = hdmi_8998_pll_recalc_rate, .prepare = hdmi_8998_pll_prepare, .unprepare = hdmi_8998_pll_unprepare, diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c b/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c index 83c8781fcc3f..6ba6bbdb7e05 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c @@ -373,12 +373,14 @@ static unsigned long hdmi_pll_recalc_rate(struct clk_hw *hw, return pll->pixclk; } -static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int hdmi_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - const struct pll_rate *pll_rate = find_rate(rate); + const struct pll_rate *pll_rate = find_rate(req->rate); + + req->rate = pll_rate->rate; - return pll_rate->rate; + return 0; } static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate, @@ -402,7 +404,7 @@ static const struct clk_ops hdmi_pll_ops = { .enable = hdmi_pll_enable, .disable = hdmi_pll_disable, .recalc_rate = hdmi_pll_recalc_rate, - .round_rate = hdmi_pll_round_rate, + .determine_rate = hdmi_pll_determine_rate, .set_rate = hdmi_pll_set_rate, }; diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 9c45d641b521..87a91148a731 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -115,7 +115,7 @@ int msm_atomic_init_pending_timer(struct msm_pending_timer *timer, timer->kms = kms; timer->crtc_idx = crtc_idx; - timer->worker = kthread_create_worker(0, "atomic-worker-%d", crtc_idx); + timer->worker = kthread_run_worker(0, "atomic-worker-%d", crtc_idx); if (IS_ERR(timer->worker)) { int ret = PTR_ERR(timer->worker); timer->worker = NULL; @@ -183,10 +183,16 @@ static unsigned get_crtc_mask(struct drm_atomic_state *state) int msm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc *crtc; - int i; + int i, ret = 0; + /* + * FIXME: stop setting allow_modeset and move this check to the DPU + * driver. + */ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if ((old_crtc_state->ctm && !new_crtc_state->ctm) || @@ -196,6 +202,11 @@ int msm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) } } + if (kms && kms->funcs && kms->funcs->check_mode_changed) + ret = kms->funcs->check_mode_changed(kms, state); + if (ret) + return ret; + return drm_atomic_helper_check(dev, state); } @@ -221,6 +232,8 @@ void msm_atomic_commit_tail(struct drm_atomic_state *state) kms->funcs->wait_flush(kms, crtc_mask); trace_msm_atomic_wait_flush_finish(crtc_mask); + atomic_set(&kms->fault_snapshot_capture, 0); + /* * Now that there is no in-progress flush, prepare the * current update: diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c index 7ab607252d18..97dc70876442 100644 --- a/drivers/gpu/drm/msm/msm_debugfs.c +++ b/drivers/gpu/drm/msm/msm_debugfs.c @@ -117,6 +117,36 @@ static const struct file_operations msm_gpu_fops = { .release = msm_gpu_release, }; +#ifdef CONFIG_DRM_MSM_KMS +static int msm_fb_show(struct seq_file *m, void *arg) +{ + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct drm_framebuffer *fb, *fbdev_fb = NULL; + + if (dev->fb_helper && dev->fb_helper->fb) { + seq_puts(m, "fbcon "); + fbdev_fb = dev->fb_helper->fb; + msm_framebuffer_describe(fbdev_fb, m); + } + + mutex_lock(&dev->mode_config.fb_lock); + list_for_each_entry(fb, &dev->mode_config.fb_list, head) { + if (fb == fbdev_fb) + continue; + + seq_puts(m, "user "); + msm_framebuffer_describe(fb, m); + } + mutex_unlock(&dev->mode_config.fb_lock); + + return 0; +} + +static struct drm_info_list msm_kms_debugfs_list[] = { + { "fb", msm_fb_show }, +}; + /* * Display Snapshot: */ @@ -180,6 +210,27 @@ static const struct file_operations msm_kms_fops = { .release = msm_kms_release, }; +static void msm_debugfs_kms_init(struct drm_minor *minor) +{ + struct drm_device *dev = minor->dev; + struct msm_drm_private *priv = dev->dev_private; + + drm_debugfs_create_files(msm_kms_debugfs_list, + ARRAY_SIZE(msm_kms_debugfs_list), + minor->debugfs_root, minor); + debugfs_create_file("kms", 0400, minor->debugfs_root, + dev, &msm_kms_fops); + + if (priv->kms->funcs->debugfs_init) + priv->kms->funcs->debugfs_init(priv->kms, minor); + +} +#else /* ! CONFIG_DRM_MSM_KMS */ +static void msm_debugfs_kms_init(struct drm_minor *minor) +{ +} +#endif + /* * Other debugfs: */ @@ -208,6 +259,35 @@ DEFINE_DEBUGFS_ATTRIBUTE(shrink_fops, shrink_get, shrink_set, "0x%08llx\n"); +/* + * Return the number of microseconds to wait until stall-on-fault is + * re-enabled. If 0 then it is already enabled or will be re-enabled on the + * next submit (unless there's a leftover devcoredump). This is useful for + * kernel tests that intentionally produce a fault and check the devcoredump to + * wait until the cooldown period is over. + */ + +static int +stall_reenable_time_get(void *data, u64 *val) +{ + struct msm_drm_private *priv = data; + unsigned long irq_flags; + + spin_lock_irqsave(&priv->fault_stall_lock, irq_flags); + + if (priv->stall_enabled) + *val = 0; + else + *val = max(ktime_us_delta(priv->stall_reenable_time, ktime_get()), 0); + + spin_unlock_irqrestore(&priv->fault_stall_lock, irq_flags); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(stall_reenable_time_fops, + stall_reenable_time_get, NULL, + "%lld\n"); static int msm_gem_show(struct seq_file *m, void *arg) { @@ -238,56 +318,35 @@ static int msm_mm_show(struct seq_file *m, void *arg) return 0; } -static int msm_fb_show(struct seq_file *m, void *arg) -{ - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_framebuffer *fb, *fbdev_fb = NULL; - - if (dev->fb_helper && dev->fb_helper->fb) { - seq_printf(m, "fbcon "); - fbdev_fb = dev->fb_helper->fb; - msm_framebuffer_describe(fbdev_fb, m); - } - - mutex_lock(&dev->mode_config.fb_lock); - list_for_each_entry(fb, &dev->mode_config.fb_list, head) { - if (fb == fbdev_fb) - continue; - - seq_printf(m, "user "); - msm_framebuffer_describe(fb, m); - } - mutex_unlock(&dev->mode_config.fb_lock); - - return 0; -} - 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 }, -}; - static int late_init_minor(struct drm_minor *minor) { + struct drm_device *dev; + struct msm_drm_private *priv; int ret; if (!minor) return 0; + dev = minor->dev; + priv = dev->dev_private; + + if (!priv->gpu_pdev) + return 0; + ret = msm_rd_debugfs_init(minor); if (ret) { - DRM_DEV_ERROR(minor->dev->dev, "could not install rd debugfs\n"); + DRM_DEV_ERROR(dev->dev, "could not install rd debugfs\n"); return ret; } ret = msm_perf_debugfs_init(minor); if (ret) { - DRM_DEV_ERROR(minor->dev->dev, "could not install perf debugfs\n"); + DRM_DEV_ERROR(dev->dev, "could not install perf debugfs\n"); return ret; } @@ -319,6 +378,9 @@ static void msm_debugfs_gpu_init(struct drm_minor *minor) debugfs_create_bool("disable_err_irq", 0600, minor->debugfs_root, &priv->disable_err_irq); + debugfs_create_file("stall_reenable_time_us", 0400, minor->debugfs_root, + priv, &stall_reenable_time_fops); + gpu_devfreq = debugfs_create_dir("devfreq", minor->debugfs_root); debugfs_create_bool("idle_clamp",0600, gpu_devfreq, @@ -343,20 +405,12 @@ void msm_debugfs_init(struct drm_minor *minor) if (priv->gpu_pdev) msm_debugfs_gpu_init(minor); - 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); - } + if (priv->kms) + msm_debugfs_kms_init(minor); debugfs_create_file("shrink", S_IRWXU, minor->debugfs_root, dev, &shrink_fops); - if (priv->kms && priv->kms->funcs->debugfs_init) - priv->kms->funcs->debugfs_init(priv->kms, minor); - fault_create_debugfs_attr("fail_gem_alloc", minor->debugfs_root, &fail_gem_alloc); fault_create_debugfs_attr("fail_gem_iova", minor->debugfs_root, diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index c2dd8ef6d6dc..7e977fec4100 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -11,7 +11,6 @@ #include <linux/of_address.h> #include <linux/uaccess.h> -#include <drm/drm_client_setup.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> #include <drm/drm_ioctl.h> @@ -41,17 +40,12 @@ * - 1.10.0 - Add MSM_SUBMIT_BO_NO_IMPLICIT * - 1.11.0 - Add wait boost (MSM_WAIT_FENCE_BOOST, MSM_PREP_BOOST) * - 1.12.0 - Add MSM_INFO_SET_METADATA and MSM_INFO_GET_METADATA + * - 1.13.0 - Add VM_BIND */ #define MSM_VERSION_MAJOR 1 -#define MSM_VERSION_MINOR 12 +#define MSM_VERSION_MINOR 13 #define MSM_VERSION_PATCHLEVEL 0 -static void msm_deinit_vram(struct drm_device *ddev); - -static char *vram = "16m"; -MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU)"); -module_param(vram, charp, 0); - bool dumpstate; MODULE_PARM_DESC(dumpstate, "Dump KMS state on errors"); module_param(dumpstate, bool, 0600); @@ -60,10 +54,19 @@ static bool modeset = true; MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (1=on (default), 0=disable)"); module_param(modeset, bool, 0600); +static bool separate_gpu_kms; +MODULE_PARM_DESC(separate_gpu_drm, "Use separate DRM device for the GPU (0=single DRM device for both GPU and display (default), 1=two DRM devices)"); +module_param(separate_gpu_kms, bool, 0400); + DECLARE_FAULT_ATTR(fail_gem_alloc); DECLARE_FAULT_ATTR(fail_gem_iova); -static int msm_drm_uninit(struct device *dev) +bool msm_gpu_no_components(void) +{ + return separate_gpu_kms; +} + +static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_ops) { struct platform_device *pdev = to_platform_device(dev); struct msm_drm_private *priv = platform_get_drvdata(pdev); @@ -79,16 +82,9 @@ static int msm_drm_uninit(struct device *dev) if (ddev->registered) { drm_dev_unregister(ddev); if (priv->kms) - drm_atomic_helper_shutdown(ddev); + msm_drm_kms_unregister(dev); } - /* We must cancel and cleanup any pending vblank enable/disable - * work before msm_irq_uninstall() to avoid work re-enabling an - * irq after uninstall has disabled it. - */ - - flush_workqueue(priv->wq); - msm_gem_shrinker_cleanup(ddev); msm_perf_debugfs_cleanup(priv); @@ -97,120 +93,19 @@ static int msm_drm_uninit(struct device *dev) if (priv->kms) msm_drm_kms_uninit(dev); - msm_deinit_vram(ddev); - - component_unbind_all(dev, ddev); + if (gpu_ops) + gpu_ops->unbind(dev, dev, NULL); + else + component_unbind_all(dev, ddev); ddev->dev_private = NULL; drm_dev_put(ddev); - destroy_workqueue(priv->wq); - return 0; } -bool msm_use_mmu(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - - /* - * a2xx comes with its own MMU - * On other platforms IOMMU can be declared specified either for the - * MDP/DPU device or for its parent, MDSS device. - */ - return priv->is_a2xx || - device_iommu_mapped(dev->dev) || - device_iommu_mapped(dev->dev->parent); -} - -static int msm_init_vram(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct device_node *node; - unsigned long size = 0; - int ret = 0; - - /* In the device-tree world, we could have a 'memory-region' - * phandle, which gives us a link to our "vram". Allocating - * is all nicely abstracted behind the dma api, but we need - * to know the entire size to allocate it all in one go. There - * are two cases: - * 1) device with no IOMMU, in which case we need exclusive - * access to a VRAM carveout big enough for all gpu - * buffers - * 2) device with IOMMU, but where the bootloader puts up - * a splash screen. In this case, the VRAM carveout - * need only be large enough for fbdev fb. But we need - * exclusive access to the buffer to avoid the kernel - * using those pages for other purposes (which appears - * as corruption on screen before we have a chance to - * load and do initial modeset) - */ - - node = of_parse_phandle(dev->dev->of_node, "memory-region", 0); - if (node) { - struct resource r; - ret = of_address_to_resource(node, 0, &r); - of_node_put(node); - if (ret) - return ret; - size = r.end - r.start + 1; - DRM_INFO("using VRAM carveout: %lx@%pa\n", size, &r.start); - - /* if we have no IOMMU, then we need to use carveout allocator. - * Grab the entire DMA chunk carved out in early startup in - * mach-msm: - */ - } else if (!msm_use_mmu(dev)) { - DRM_INFO("using %s VRAM carveout\n", vram); - size = memparse(vram, NULL); - } - - if (size) { - unsigned long attrs = 0; - void *p; - - priv->vram.size = size; - - drm_mm_init(&priv->vram.mm, 0, (size >> PAGE_SHIFT) - 1); - spin_lock_init(&priv->vram.lock); - - attrs |= DMA_ATTR_NO_KERNEL_MAPPING; - attrs |= DMA_ATTR_WRITE_COMBINE; - - /* note that for no-kernel-mapping, the vaddr returned - * is bogus, but non-null if allocation succeeded: - */ - p = dma_alloc_attrs(dev->dev, size, - &priv->vram.paddr, GFP_KERNEL, attrs); - if (!p) { - DRM_DEV_ERROR(dev->dev, "failed to allocate VRAM\n"); - priv->vram.paddr = 0; - return -ENOMEM; - } - - DRM_DEV_INFO(dev->dev, "VRAM: %08x->%08x\n", - (uint32_t)priv->vram.paddr, - (uint32_t)(priv->vram.paddr + size)); - } - - return ret; -} - -static void msm_deinit_vram(struct drm_device *ddev) -{ - struct msm_drm_private *priv = ddev->dev_private; - unsigned long attrs = DMA_ATTR_NO_KERNEL_MAPPING; - - if (!priv->vram.paddr) - return; - - drm_mm_takedown(&priv->vram.mm); - dma_free_attrs(ddev->dev, priv->vram.size, NULL, priv->vram.paddr, - attrs); -} - -static int msm_drm_init(struct device *dev, const struct drm_driver *drv) +static int msm_drm_init(struct device *dev, const struct drm_driver *drv, + const struct component_ops *gpu_ops) { struct msm_drm_private *priv = dev_get_drvdata(dev); struct drm_device *ddev; @@ -227,12 +122,6 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) ddev->dev_private = priv; priv->dev = ddev; - priv->wq = alloc_ordered_workqueue("msm", 0); - if (!priv->wq) { - ret = -ENOMEM; - goto err_put_dev; - } - INIT_LIST_HEAD(&priv->objects); mutex_init(&priv->obj_lock); @@ -245,6 +134,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) drm_gem_lru_init(&priv->lru.willneed, &priv->lru.lock); drm_gem_lru_init(&priv->lru.dontneed, &priv->lru.lock); + /* Initialize stall-on-fault */ + spin_lock_init(&priv->fault_stall_lock); + priv->stall_enabled = true; + /* Teach lockdep about lock ordering wrt. shrinker: */ fs_reclaim_acquire(GFP_KERNEL); might_lock(&priv->lru.lock); @@ -253,19 +146,18 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) if (priv->kms_init) { ret = drmm_mode_config_init(ddev); if (ret) - goto err_destroy_wq; + goto err_put_dev; } - ret = msm_init_vram(ddev); - if (ret) - goto err_destroy_wq; - dma_set_max_seg_size(dev, UINT_MAX); /* Bind all our sub-components: */ - ret = component_bind_all(dev, ddev); + if (gpu_ops) + ret = gpu_ops->bind(dev, dev, NULL); + else + ret = component_bind_all(dev, ddev); if (ret) - goto err_deinit_vram; + goto err_put_dev; ret = msm_gem_shrinker_init(ddev); if (ret) @@ -275,11 +167,6 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) ret = msm_drm_kms_init(dev, drv); if (ret) goto err_msm_uninit; - } else { - /* valid only for the dummy headless case, where of_node=NULL */ - WARN_ON(dev->of_node); - ddev->driver_features &= ~DRIVER_MODESET; - ddev->driver_features &= ~DRIVER_ATOMIC; } ret = drm_dev_register(ddev, 0); @@ -290,22 +177,16 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) if (ret) goto err_msm_uninit; - if (priv->kms_init) { - drm_kms_helper_poll_init(ddev); - drm_client_setup(ddev, NULL); - } + if (priv->kms_init) + msm_drm_kms_post_init(dev); return 0; err_msm_uninit: - msm_drm_uninit(dev); + msm_drm_uninit(dev, gpu_ops); return ret; -err_deinit_vram: - msm_deinit_vram(ddev); -err_destroy_wq: - destroy_workqueue(priv->wq); err_put_dev: drm_dev_put(ddev); @@ -329,11 +210,42 @@ static void load_gpu(struct drm_device *dev) mutex_unlock(&init_lock); } +/** + * msm_context_vm - lazily create the context's VM + * + * @dev: the drm device + * @ctx: the context + * + * The VM is lazily created, so that userspace has a chance to opt-in to having + * a userspace managed VM before the VM is created. + * + * Note that this does not return a reference to the VM. Once the VM is created, + * it exists for the lifetime of the context. + */ +struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx) +{ + static DEFINE_MUTEX(init_lock); + struct msm_drm_private *priv = dev->dev_private; + + /* Once ctx->vm is created it is valid for the lifetime of the context: */ + if (ctx->vm) + return ctx->vm; + + mutex_lock(&init_lock); + if (!ctx->vm) { + ctx->vm = msm_gpu_create_private_vm( + priv->gpu, current, !ctx->userspace_managed_vm); + + } + mutex_unlock(&init_lock); + + return ctx->vm; +} + static int context_init(struct drm_device *dev, struct drm_file *file) { static atomic_t ident = ATOMIC_INIT(0); - struct msm_drm_private *priv = dev->dev_private; - struct msm_file_private *ctx; + struct msm_context *ctx; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -345,7 +257,6 @@ static int context_init(struct drm_device *dev, struct drm_file *file) kref_init(&ctx->ref); msm_submitqueue_init(dev, ctx); - ctx->aspace = msm_gpu_create_private_address_space(priv->gpu, current); file->driver_priv = ctx; ctx->seqno = atomic_inc_return(&ident); @@ -363,23 +274,24 @@ static int msm_open(struct drm_device *dev, struct drm_file *file) return context_init(dev, file); } -static void context_close(struct msm_file_private *ctx) +static void context_close(struct msm_context *ctx) { + ctx->closed = true; msm_submitqueue_close(ctx); - msm_file_private_put(ctx); + msm_context_put(ctx); } static void msm_postclose(struct drm_device *dev, struct drm_file *file) { struct msm_drm_private *priv = dev->dev_private; - struct msm_file_private *ctx = file->driver_priv; + struct msm_context *ctx = file->driver_priv; /* * It is not possible to set sysprof param to non-zero if gpu * is not initialized: */ if (priv->gpu) - msm_file_private_set_sysprof(ctx, priv->gpu, 0); + msm_context_set_sysprof(ctx, priv->gpu, 0); context_close(ctx); } @@ -511,11 +423,14 @@ static int msm_ioctl_gem_info_iova(struct drm_device *dev, uint64_t *iova) { struct msm_drm_private *priv = dev->dev_private; - struct msm_file_private *ctx = file->driver_priv; + struct msm_context *ctx = file->driver_priv; if (!priv->gpu) return -EINVAL; + if (msm_context_is_vmbind(ctx)) + return UERR(EINVAL, dev, "VM_BIND is enabled"); + if (should_fail(&fail_gem_iova, obj->size)) return -ENOMEM; @@ -523,7 +438,7 @@ static int msm_ioctl_gem_info_iova(struct drm_device *dev, * Don't pin the memory here - just get an address so that userspace can * be productive */ - return msm_gem_get_iova(obj, ctx->aspace, iova); + return msm_gem_get_iova(obj, msm_context_vm(dev, ctx), iova); } static int msm_ioctl_gem_info_set_iova(struct drm_device *dev, @@ -531,19 +446,23 @@ static int msm_ioctl_gem_info_set_iova(struct drm_device *dev, uint64_t iova) { struct msm_drm_private *priv = dev->dev_private; - struct msm_file_private *ctx = file->driver_priv; + struct msm_context *ctx = file->driver_priv; + struct drm_gpuvm *vm = msm_context_vm(dev, ctx); if (!priv->gpu) return -EINVAL; + if (msm_context_is_vmbind(ctx)) + return UERR(EINVAL, dev, "VM_BIND is enabled"); + /* Only supported if per-process address space is supported: */ - if (priv->gpu->aspace == ctx->aspace) - return -EOPNOTSUPP; + if (priv->gpu->vm == vm) + return UERR(EOPNOTSUPP, dev, "requires per-process pgtables"); if (should_fail(&fail_gem_iova, obj->size)) return -ENOMEM; - return msm_gem_set_iova(obj, ctx->aspace, iova); + return msm_gem_set_iova(obj, vm, iova); } static int msm_ioctl_gem_info_set_metadata(struct drm_gem_object *obj, @@ -551,6 +470,7 @@ static int msm_ioctl_gem_info_set_metadata(struct drm_gem_object *obj, u32 metadata_size) { struct msm_gem_object *msm_obj = to_msm_bo(obj); + void *new_metadata; void *buf; int ret; @@ -568,8 +488,14 @@ static int msm_ioctl_gem_info_set_metadata(struct drm_gem_object *obj, if (ret) goto out; - msm_obj->metadata = + new_metadata = krealloc(msm_obj->metadata, metadata_size, GFP_KERNEL); + if (!new_metadata) { + ret = -ENOMEM; + goto out; + } + + msm_obj->metadata = new_metadata; msm_obj->metadata_size = metadata_size; memcpy(msm_obj->metadata, buf, metadata_size); @@ -671,7 +597,7 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, ret = msm_ioctl_gem_info_set_iova(dev, file, obj, args->value); break; case MSM_INFO_GET_FLAGS: - if (obj->import_attach) { + if (drm_gem_is_imported(obj)) { ret = -EINVAL; break; } @@ -868,6 +794,7 @@ static const struct drm_ioctl_desc msm_ioctls[] = { DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW, msm_ioctl_submitqueue_new, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_VM_BIND, msm_ioctl_vm_bind, DRM_RENDER_ALLOW), }; static void msm_show_fdinfo(struct drm_printer *p, struct drm_file *file) @@ -889,12 +816,46 @@ static const struct file_operations fops = { .show_fdinfo = drm_show_fdinfo, }; +#define DRIVER_FEATURES_GPU ( \ + DRIVER_GEM | \ + DRIVER_GEM_GPUVA | \ + DRIVER_RENDER | \ + DRIVER_SYNCOBJ | \ + DRIVER_SYNCOBJ_TIMELINE | \ + 0 ) + +#define DRIVER_FEATURES_KMS ( \ + DRIVER_GEM | \ + DRIVER_GEM_GPUVA | \ + DRIVER_ATOMIC | \ + DRIVER_MODESET | \ + 0 ) + static const struct drm_driver msm_driver = { - .driver_features = DRIVER_GEM | - DRIVER_RENDER | - DRIVER_ATOMIC | - DRIVER_MODESET | - DRIVER_SYNCOBJ, + .driver_features = DRIVER_FEATURES_GPU | DRIVER_FEATURES_KMS, + .open = msm_open, + .postclose = msm_postclose, + .dumb_create = msm_gem_dumb_create, + .dumb_map_offset = msm_gem_dumb_map_offset, + .gem_prime_import = msm_gem_prime_import, + .gem_prime_import_sg_table = msm_gem_prime_import_sg_table, +#ifdef CONFIG_DEBUG_FS + .debugfs_init = msm_debugfs_init, +#endif + MSM_FBDEV_DRIVER_OPS, + .show_fdinfo = msm_show_fdinfo, + .ioctls = msm_ioctls, + .num_ioctls = ARRAY_SIZE(msm_ioctls), + .fops = &fops, + .name = "msm", + .desc = "MSM Snapdragon DRM", + .major = MSM_VERSION_MAJOR, + .minor = MSM_VERSION_MINOR, + .patchlevel = MSM_VERSION_PATCHLEVEL, +}; + +static const struct drm_driver msm_kms_driver = { + .driver_features = DRIVER_FEATURES_KMS, .open = msm_open, .postclose = msm_postclose, .dumb_create = msm_gem_dumb_create, @@ -905,12 +866,28 @@ static const struct drm_driver msm_driver = { #endif MSM_FBDEV_DRIVER_OPS, .show_fdinfo = msm_show_fdinfo, + .fops = &fops, + .name = "msm-kms", + .desc = "MSM Snapdragon DRM", + .major = MSM_VERSION_MAJOR, + .minor = MSM_VERSION_MINOR, + .patchlevel = MSM_VERSION_PATCHLEVEL, +}; + +static const struct drm_driver msm_gpu_driver = { + .driver_features = DRIVER_FEATURES_GPU, + .open = msm_open, + .postclose = msm_postclose, + .gem_prime_import_sg_table = msm_gem_prime_import_sg_table, +#ifdef CONFIG_DEBUG_FS + .debugfs_init = msm_debugfs_init, +#endif + .show_fdinfo = msm_show_fdinfo, .ioctls = msm_ioctls, .num_ioctls = ARRAY_SIZE(msm_ioctls), .fops = &fops, .name = "msm", .desc = "MSM Snapdragon DRM", - .date = "20130625", .major = MSM_VERSION_MAJOR, .minor = MSM_VERSION_MINOR, .patchlevel = MSM_VERSION_PATCHLEVEL, @@ -926,7 +903,7 @@ static const struct drm_driver msm_driver = { * is no external component that we need to add since LVDS is within MDP4 * itself. */ -static int add_components_mdp(struct device *master_dev, +static int add_mdp_components(struct device *master_dev, struct component_match **matchptr) { struct device_node *np = master_dev->of_node; @@ -1030,7 +1007,7 @@ static int add_gpu_components(struct device *dev, if (!np) return 0; - if (of_device_is_available(np)) + if (of_device_is_available(np) && adreno_has_gpu(np)) drm_of_component_match_add(dev, matchptr, component_compare_of, np); of_node_put(np); @@ -1040,12 +1017,16 @@ static int add_gpu_components(struct device *dev, static int msm_drm_bind(struct device *dev) { - return msm_drm_init(dev, &msm_driver); + return msm_drm_init(dev, + msm_gpu_no_components() ? + &msm_kms_driver : + &msm_driver, + NULL); } static void msm_drm_unbind(struct device *dev) { - msm_drm_uninit(dev); + msm_drm_uninit(dev, NULL); } const struct component_master_ops msm_drm_ops = { @@ -1071,14 +1052,16 @@ int msm_drv_probe(struct device *master_dev, /* Add mdp components if we have KMS. */ if (kms_init) { - ret = add_components_mdp(master_dev, &match); + ret = add_mdp_components(master_dev, &match); if (ret) return ret; } - ret = add_gpu_components(master_dev, &match); - if (ret) - return ret; + if (!msm_gpu_no_components()) { + ret = add_gpu_components(master_dev, &match); + if (ret) + return ret; + } /* on all devices that I am aware of, iommu's which can map * any address the cpu can see are used: @@ -1094,29 +1077,34 @@ int msm_drv_probe(struct device *master_dev, return 0; } -/* - * Platform driver: - * Used only for headlesss GPU instances - */ - -static int msm_pdev_probe(struct platform_device *pdev) +int msm_gpu_probe(struct platform_device *pdev, + const struct component_ops *ops) { - return msm_drv_probe(&pdev->dev, NULL, NULL); + struct msm_drm_private *priv; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + + /* on all devices that I am aware of, iommu's which can map + * any address the cpu can see are used: + */ + ret = dma_set_mask_and_coherent(&pdev->dev, ~0); + if (ret) + return ret; + + return msm_drm_init(&pdev->dev, &msm_gpu_driver, ops); } -static void msm_pdev_remove(struct platform_device *pdev) +void msm_gpu_remove(struct platform_device *pdev, + const struct component_ops *ops) { - component_master_del(&pdev->dev, &msm_drm_ops); + msm_drm_uninit(&pdev->dev, ops); } -static struct platform_driver msm_platform_driver = { - .probe = msm_pdev_probe, - .remove_new = msm_pdev_remove, - .driver = { - .name = "msm", - }, -}; - static int __init msm_drm_register(void) { if (!modeset) @@ -1131,13 +1119,13 @@ static int __init msm_drm_register(void) adreno_register(); msm_mdp4_register(); msm_mdss_register(); - return platform_driver_register(&msm_platform_driver); + + return 0; } static void __exit msm_drm_unregister(void) { DBG("fini"); - platform_driver_unregister(&msm_platform_driver); msm_mdss_unregister(); msm_mdp4_unregister(); msm_dp_unregister(); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index d8c9a1b19263..6d847d593f1a 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -28,6 +28,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/display/drm_dsc.h> #include <drm/msm_drm.h> @@ -47,8 +48,6 @@ struct msm_rd_state; struct msm_perf_state; struct msm_gem_submit; struct msm_fence_context; -struct msm_gem_address_space; -struct msm_gem_vma; struct msm_disp_state; #define MAX_CRTCS 8 @@ -71,12 +70,6 @@ enum msm_dsi_controller { #define MSM_GPU_MAX_RINGS 4 -/* Commit/Event thread specific structure */ -struct msm_drm_thread { - struct drm_device *dev; - struct kthread_worker *worker; -}; - struct msm_drm_private { struct drm_device *dev; @@ -87,16 +80,6 @@ struct msm_drm_private { /* subordinate devices, if present: */ struct platform_device *gpu_pdev; - /* possibly this should be in the kms component, but it is - * shared by both mdp4 and mdp5.. - */ - struct hdmi *hdmi; - - /* DSI is shared by mdp4 and mdp5 */ - struct msm_dsi *dsi[MSM_DSI_CONTROLLER_COUNT]; - - struct msm_dp *dp[MSM_DP_CONTROLLER_COUNT]; - /* when we have more than one 'msm_gpu' these need to be an array: */ struct msm_gpu *gpu; @@ -176,23 +159,6 @@ struct msm_drm_private { struct mutex lock; } lru; - struct workqueue_struct *wq; - - unsigned int num_crtcs; - - struct msm_drm_thread event_thread[MAX_CRTCS]; - - /* VRAM carveout, used when no IOMMU: */ - struct { - unsigned long size; - dma_addr_t paddr; - /* NOTE: mm managed at the page level, size is in # of pages - * and position mm_node->start is in # of pages: - */ - struct drm_mm mm; - spinlock_t lock; /* Protects drm_mm node allocation/removal */ - } vram; - struct notifier_block vmap_notifier; struct shrinker *shrinker; @@ -221,6 +187,29 @@ struct msm_drm_private { * the sw hangcheck mechanism. */ bool disable_err_irq; + + /** + * @fault_stall_lock: + * + * Serialize changes to stall-on-fault state. + */ + spinlock_t fault_stall_lock; + + /** + * @fault_stall_reenable_time: + * + * If stall_enabled is false, when to reenable stall-on-fault. + * Protected by @fault_stall_lock. + */ + ktime_t stall_reenable_time; + + /** + * @stall_enabled: + * + * Whether stall-on-fault is currently enabled. Protected by + * @fault_stall_lock. + */ + bool stall_enabled; }; const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, uint64_t modifier); @@ -240,11 +229,13 @@ void msm_crtc_disable_vblank(struct drm_crtc *crtc); int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu); void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu); -struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev); +struct drm_gpuvm *msm_kms_init_vm(struct drm_device *dev, struct device *mdss_dev); bool msm_use_mmu(struct drm_device *dev); int msm_ioctl_gem_submit(struct drm_device *dev, void *data, - struct drm_file *file); + struct drm_file *file); +int msm_ioctl_vm_bind(struct drm_device *dev, void *data, + struct drm_file *file); #ifdef CONFIG_DEBUG_FS unsigned long msm_gem_shrinker_shrink(struct drm_device *dev, unsigned long nr_to_scan); @@ -256,25 +247,25 @@ void msm_gem_shrinker_cleanup(struct drm_device *dev); struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj); 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); +struct drm_gem_object *msm_gem_prime_import(struct drm_device *dev, struct dma_buf *buf); struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sg); +struct dma_buf *msm_gem_prime_export(struct drm_gem_object *obj, int flags); int msm_gem_prime_pin(struct drm_gem_object *obj); void msm_gem_prime_unpin(struct drm_gem_object *obj); -int msm_framebuffer_prepare(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace, bool needs_dirtyfb); -void msm_framebuffer_cleanup(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace, bool needed_dirtyfb); -uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace, int plane); +int msm_framebuffer_prepare(struct drm_framebuffer *fb, bool needs_dirtyfb); +void msm_framebuffer_cleanup(struct drm_framebuffer *fb, bool needed_dirtyfb); +uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, int plane); struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane); const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb); struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, - struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd); + struct drm_file *file, const struct drm_format_info *info, + const struct drm_mode_fb_cmd2 *mode_cmd); struct drm_framebuffer * msm_alloc_stolen_fb(struct drm_device *dev, int w, int h, int p, uint32_t format); -#ifdef CONFIG_DRM_FBDEV_EMULATION +#ifdef CONFIG_DRM_MSM_KMS_FBDEV int msm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes); #define MSM_FBDEV_DRIVER_OPS \ @@ -359,6 +350,7 @@ static inline const char *msm_dsi_get_te_source(struct msm_dsi *msm_dsi) } #endif +struct msm_dp; #ifdef CONFIG_DRM_MSM_DP int __init msm_dp_register(void); void __exit msm_dp_unregister(void); @@ -506,6 +498,12 @@ void msm_hrtimer_work_init(struct msm_hrtimer_work *work, clockid_t clock_id, enum hrtimer_mode mode); +/* Helper for returning a UABI error with optional logging which can make + * it easier for userspace to understand what it is doing wrong. + */ +#define UERR(err, drm, fmt, ...) \ + ({ DRM_DEV_DEBUG_DRIVER((drm)->dev, fmt, ##__VA_ARGS__); -(err); }) + #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) @@ -530,15 +528,12 @@ static inline int align_pitch(int width, int bpp) static inline unsigned long timeout_to_jiffies(const ktime_t *timeout) { ktime_t now = ktime_get(); - s64 remaining_jiffies; - if (ktime_compare(*timeout, now) < 0) { - remaining_jiffies = 0; - } else { - ktime_t rem = ktime_sub(*timeout, now); - remaining_jiffies = ktime_divns(rem, NSEC_PER_SEC / HZ); - } + if (ktime_compare(*timeout, now) <= 0) + return 0; + ktime_t rem = ktime_sub(*timeout, now); + s64 remaining_jiffies = ktime_divns(rem, NSEC_PER_SEC / HZ); return clamp(remaining_jiffies, 1LL, (s64)INT_MAX); } @@ -549,6 +544,10 @@ extern const struct component_master_ops msm_drm_ops; int msm_kms_pm_prepare(struct device *dev); void msm_kms_pm_complete(struct device *dev); +int msm_gpu_probe(struct platform_device *pdev, + const struct component_ops *ops); +void msm_gpu_remove(struct platform_device *pdev, + const struct component_ops *ops); int msm_drv_probe(struct device *dev, int (*kms_init)(struct drm_device *dev), struct msm_kms *kms); @@ -556,4 +555,6 @@ void msm_kms_shutdown(struct platform_device *pdev); bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver); +bool msm_gpu_no_components(void); + #endif /* __MSM_DRV_H__ */ diff --git a/drivers/gpu/drm/msm/msm_dsc_helper.h b/drivers/gpu/drm/msm/msm_dsc_helper.h index b9049fe1e279..63f95523b2cb 100644 --- a/drivers/gpu/drm/msm/msm_dsc_helper.h +++ b/drivers/gpu/drm/msm/msm_dsc_helper.h @@ -13,17 +13,6 @@ #include <drm/display/drm_dsc_helper.h> /** - * msm_dsc_get_slices_per_intf() - calculate number of slices per interface - * @dsc: Pointer to drm dsc config struct - * @intf_width: interface width in pixels - * Returns: Integer representing the number of slices for the given interface - */ -static inline u32 msm_dsc_get_slices_per_intf(const struct drm_dsc_config *dsc, u32 intf_width) -{ - return DIV_ROUND_UP(intf_width, dsc->slice_width); -} - -/** * msm_dsc_get_bytes_per_line() - calculate bytes per line * @dsc: Pointer to drm dsc config struct * Returns: Integer value representing bytes per line. DSI and DP need diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 09268e416843..1eff615ff9bf 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -30,6 +30,7 @@ struct msm_framebuffer { #define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base) static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, + const struct drm_format_info *info, const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos); static int msm_framebuffer_dirtyfb(struct drm_framebuffer *fb, @@ -75,20 +76,22 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) /* prepare/pin all the fb's bo's for scanout. */ -int msm_framebuffer_prepare(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace, - bool needs_dirtyfb) +int msm_framebuffer_prepare(struct drm_framebuffer *fb, bool needs_dirtyfb) { + struct msm_drm_private *priv = fb->dev->dev_private; + struct drm_gpuvm *vm = priv->kms->vm; struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int ret, i, n = fb->format->num_planes; if (needs_dirtyfb) refcount_inc(&msm_fb->dirtyfb); - atomic_inc(&msm_fb->prepare_count); + if (atomic_inc_return(&msm_fb->prepare_count) > 1) + return 0; for (i = 0; i < n; i++) { - ret = msm_gem_get_and_pin_iova(fb->obj[i], aspace, &msm_fb->iova[i]); + msm_gem_vma_get(fb->obj[i]); + ret = msm_gem_get_and_pin_iova(fb->obj[i], vm, &msm_fb->iova[i]); drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)\n", fb->base.id, i, msm_fb->iova[i], ret); if (ret) @@ -98,25 +101,28 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb, return 0; } -void msm_framebuffer_cleanup(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace, - bool needed_dirtyfb) +void msm_framebuffer_cleanup(struct drm_framebuffer *fb, bool needed_dirtyfb) { + struct msm_drm_private *priv = fb->dev->dev_private; + struct drm_gpuvm *vm = priv->kms->vm; struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int i, n = fb->format->num_planes; if (needed_dirtyfb) refcount_dec(&msm_fb->dirtyfb); - for (i = 0; i < n; i++) - msm_gem_unpin_iova(fb->obj[i], aspace); + if (atomic_dec_return(&msm_fb->prepare_count)) + return; + + memset(msm_fb->iova, 0, sizeof(msm_fb->iova)); - if (!atomic_dec_return(&msm_fb->prepare_count)) - memset(msm_fb->iova, 0, sizeof(msm_fb->iova)); + for (i = 0; i < n; i++) { + msm_gem_unpin_iova(fb->obj[i], vm); + msm_gem_vma_put(fb->obj[i]); + } } -uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace, int plane) +uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, int plane) { struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); return msm_fb->iova[plane] + fb->offsets[plane]; @@ -134,10 +140,9 @@ const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb) } struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, - struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd) + struct drm_file *file, const struct drm_format_info *info, + const struct drm_mode_fb_cmd2 *mode_cmd) { - const struct drm_format_info *info = drm_get_format_info(dev, - mode_cmd); struct drm_gem_object *bos[4] = {0}; struct drm_framebuffer *fb; int ret, i, n = info->num_planes; @@ -150,7 +155,7 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, } } - fb = msm_framebuffer_init(dev, mode_cmd, bos); + fb = msm_framebuffer_init(dev, info, mode_cmd, bos); if (IS_ERR(fb)) { ret = PTR_ERR(fb); goto out_unref; @@ -165,10 +170,9 @@ out_unref: } static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, + const struct drm_format_info *info, const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos) { - const struct drm_format_info *info = drm_get_format_info(dev, - mode_cmd); struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; struct msm_framebuffer *msm_fb = NULL; @@ -222,7 +226,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, msm_fb->base.obj[i] = bos[i]; } - drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, fb, info, mode_cmd); ret = drm_framebuffer_init(dev, fb, &msm_framebuffer_funcs); if (ret) { @@ -271,7 +275,10 @@ msm_alloc_stolen_fb(struct drm_device *dev, int w, int h, int p, uint32_t format msm_gem_object_set_name(bo, "stolenfb"); - fb = msm_framebuffer_init(dev, &mode_cmd, &bo); + fb = msm_framebuffer_init(dev, + drm_get_format_info(dev, mode_cmd.pixel_format, + mode_cmd.modifier[0]), + &mode_cmd, &bo); if (IS_ERR(fb)) { DRM_DEV_ERROR(dev->dev, "failed to allocate fb\n"); /* note: if fb creation failed, we can't rely on fb destroy diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index c62249b1ab3d..fd19995b12b5 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -52,8 +52,6 @@ static void msm_fbdev_fb_destroy(struct fb_info *info) drm_framebuffer_remove(fb); drm_client_release(&helper->client); - drm_fb_helper_unprepare(helper); - kfree(helper); } static const struct fb_ops msm_fb_ops = { @@ -93,9 +91,9 @@ int msm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, { struct drm_device *dev = helper->dev; struct msm_drm_private *priv = dev->dev_private; + struct fb_info *fbi = helper->info; struct drm_framebuffer *fb = NULL; struct drm_gem_object *bo; - struct fb_info *fbi = NULL; uint64_t paddr; uint32_t format; int ret, pitch; @@ -122,19 +120,12 @@ int msm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, * in panic (ie. lock-safe, etc) we could avoid pinning the * buffer now: */ - ret = msm_gem_get_and_pin_iova(bo, priv->kms->aspace, &paddr); + ret = msm_gem_get_and_pin_iova(bo, priv->kms->vm, &paddr); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to get buffer obj iova: %d\n", ret); goto fail; } - fbi = drm_fb_helper_alloc_info(helper); - if (IS_ERR(fbi)) { - DRM_DEV_ERROR(dev->dev, "failed to allocate fb info\n"); - ret = PTR_ERR(fbi); - goto fail; - } - DBG("fbi=%p, dev=%p", fbi, dev); helper->funcs = &msm_fbdev_helper_funcs; diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c index 1a5d4f1c8b42..d41e5a6bbee0 100644 --- a/drivers/gpu/drm/msm/msm_fence.c +++ b/drivers/gpu/drm/msm/msm_fence.c @@ -65,8 +65,7 @@ msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr, fctx->completed_fence = fctx->last_fence; *fctx->fenceptr = fctx->last_fence; - hrtimer_init(&fctx->deadline_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - fctx->deadline_timer.function = deadline_timer; + hrtimer_setup(&fctx->deadline_timer, deadline_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); kthread_init_work(&fctx->deadline_work, deadline_work); diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index ebc9ba66efb8..017411a0bf45 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -9,32 +9,18 @@ #include <linux/spinlock.h> #include <linux/shmem_fs.h> #include <linux/dma-buf.h> -#include <linux/pfn_t.h> +#include <drm/drm_dumb_buffers.h> #include <drm/drm_prime.h> #include <drm/drm_file.h> +#include <drm/drm_fourcc.h> #include <trace/events/gpu_mem.h> #include "msm_drv.h" -#include "msm_fence.h" #include "msm_gem.h" #include "msm_gpu.h" -#include "msm_mmu.h" - -static dma_addr_t physaddr(struct drm_gem_object *obj) -{ - struct msm_gem_object *msm_obj = to_msm_bo(obj); - struct msm_drm_private *priv = obj->dev->dev_private; - return (((dma_addr_t)msm_obj->vram_node->start) << PAGE_SHIFT) + - priv->vram.paddr; -} - -static bool use_pages(struct drm_gem_object *obj) -{ - struct msm_gem_object *msm_obj = to_msm_bo(obj); - return !msm_obj->vram_node; -} +#include "msm_kms.h" static void update_device_mem(struct msm_drm_private *priv, ssize_t size) { @@ -44,7 +30,7 @@ static void update_device_mem(struct msm_drm_private *priv, ssize_t size) static void update_ctx_mem(struct drm_file *file, ssize_t size) { - struct msm_file_private *ctx = file->driver_priv; + struct msm_context *ctx = file->driver_priv; uint64_t ctx_mem = atomic64_add_return(size, &ctx->ctx_mem); rcu_read_lock(); /* Locks file->pid! */ @@ -55,13 +41,76 @@ static void update_ctx_mem(struct drm_file *file, ssize_t size) static int msm_gem_open(struct drm_gem_object *obj, struct drm_file *file) { + msm_gem_vma_get(obj); update_ctx_mem(file, obj->size); return 0; } +static void put_iova_spaces(struct drm_gem_object *obj, struct drm_gpuvm *vm, + bool close, const char *reason); + static void msm_gem_close(struct drm_gem_object *obj, struct drm_file *file) { + struct msm_context *ctx = file->driver_priv; + struct drm_exec exec; + update_ctx_mem(file, -obj->size); + msm_gem_vma_put(obj); + + /* + * If VM isn't created yet, nothing to cleanup. And in fact calling + * put_iova_spaces() with vm=NULL would be bad, in that it will tear- + * down the mappings of shared buffers in other contexts. + */ + if (!ctx->vm) + return; + + /* + * VM_BIND does not depend on implicit teardown of VMAs on handle + * close, but instead on implicit teardown of the VM when the device + * is closed (see msm_gem_vm_close()) + */ + if (msm_context_is_vmbind(ctx)) + return; + + /* + * TODO we might need to kick this to a queue to avoid blocking + * in CLOSE ioctl + */ + dma_resv_wait_timeout(obj->resv, DMA_RESV_USAGE_BOOKKEEP, false, + MAX_SCHEDULE_TIMEOUT); + + msm_gem_lock_vm_and_obj(&exec, obj, ctx->vm); + put_iova_spaces(obj, ctx->vm, true, "close"); + drm_exec_fini(&exec); /* drop locks */ +} + +/* + * Get/put for kms->vm VMA + */ + +void msm_gem_vma_get(struct drm_gem_object *obj) +{ + atomic_inc(&to_msm_bo(obj)->vma_ref); +} + +void msm_gem_vma_put(struct drm_gem_object *obj) +{ + struct msm_drm_private *priv = obj->dev->dev_private; + + if (atomic_dec_return(&to_msm_bo(obj)->vma_ref)) + return; + + if (!priv->kms) + return; + +#ifdef CONFIG_DRM_MSM_KMS + struct drm_exec exec; + + msm_gem_lock_vm_and_obj(&exec, obj, priv->kms->vm); + put_iova_spaces(obj, priv->kms->vm, true, "vma_put"); + drm_exec_fini(&exec); /* drop locks */ +#endif } /* @@ -135,36 +184,6 @@ static void update_lru(struct drm_gem_object *obj) mutex_unlock(&priv->lru.lock); } -/* allocate pages from VRAM carveout, used when no IOMMU: */ -static struct page **get_pages_vram(struct drm_gem_object *obj, int npages) -{ - struct msm_gem_object *msm_obj = to_msm_bo(obj); - struct msm_drm_private *priv = obj->dev->dev_private; - dma_addr_t paddr; - struct page **p; - int ret, i; - - p = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); - if (!p) - return ERR_PTR(-ENOMEM); - - spin_lock(&priv->vram.lock); - ret = drm_mm_insert_node(&priv->vram.mm, msm_obj->vram_node, npages); - spin_unlock(&priv->vram.lock); - if (ret) { - kvfree(p); - return ERR_PTR(ret); - } - - paddr = physaddr(obj); - for (i = 0; i < npages; i++) { - p[i] = pfn_to_page(__phys_to_pfn(paddr)); - paddr += PAGE_SIZE; - } - - return p; -} - static struct page **get_pages(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); @@ -174,12 +193,9 @@ static struct page **get_pages(struct drm_gem_object *obj) if (!msm_obj->pages) { struct drm_device *dev = obj->dev; struct page **p; - int npages = obj->size >> PAGE_SHIFT; + size_t npages = obj->size >> PAGE_SHIFT; - if (use_pages(obj)) - p = drm_gem_get_pages(obj); - else - p = get_pages_vram(obj, npages); + p = drm_gem_get_pages(obj); if (IS_ERR(p)) { DRM_DEV_ERROR(dev->dev, "could not get pages: %ld\n", @@ -212,22 +228,17 @@ static struct page **get_pages(struct drm_gem_object *obj) return msm_obj->pages; } -static void put_pages_vram(struct drm_gem_object *obj) -{ - struct msm_gem_object *msm_obj = to_msm_bo(obj); - struct msm_drm_private *priv = obj->dev->dev_private; - - spin_lock(&priv->vram.lock); - drm_mm_remove_node(msm_obj->vram_node); - spin_unlock(&priv->vram.lock); - - kvfree(msm_obj->pages); -} - static void put_pages(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); + /* + * Skip gpuvm in the object free path to avoid a WARN_ON() splat. + * See explaination in msm_gem_assert_locked() + */ + if (kref_read(&obj->refcount)) + drm_gpuvm_bo_gem_evict(obj, true); + if (msm_obj->pages) { if (msm_obj->sgt) { /* For non-cached buffers, ensure the new @@ -244,18 +255,14 @@ static void put_pages(struct drm_gem_object *obj) update_device_mem(obj->dev->dev_private, -obj->size); - if (use_pages(obj)) - drm_gem_put_pages(obj, msm_obj->pages, true, false); - else - put_pages_vram(obj); + drm_gem_put_pages(obj, msm_obj->pages, true, false); msm_obj->pages = NULL; update_lru(obj); } } -static struct page **msm_gem_get_pages_locked(struct drm_gem_object *obj, - unsigned madv) +struct page **msm_gem_get_pages_locked(struct drm_gem_object *obj, unsigned madv) { struct msm_gem_object *msm_obj = to_msm_bo(obj); @@ -397,48 +404,31 @@ uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj) return offset; } -static struct msm_gem_vma *add_vma(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace) +static struct drm_gpuva *lookup_vma(struct drm_gem_object *obj, + struct drm_gpuvm *vm) { - struct msm_gem_object *msm_obj = to_msm_bo(obj); - struct msm_gem_vma *vma; + struct drm_gpuvm_bo *vm_bo; msm_gem_assert_locked(obj); - vma = msm_gem_vma_new(aspace); - if (!vma) - return ERR_PTR(-ENOMEM); + drm_gem_for_each_gpuvm_bo (vm_bo, obj) { + struct drm_gpuva *vma; - list_add_tail(&vma->list, &msm_obj->vmas); + drm_gpuvm_bo_for_each_va (vma, vm_bo) { + if (vma->vm == vm) { + /* lookup_vma() should only be used in paths + * with at most one vma per vm + */ + GEM_WARN_ON(!list_is_singular(&vm_bo->list.gpuva)); - return vma; -} - -static struct msm_gem_vma *lookup_vma(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace) -{ - struct msm_gem_object *msm_obj = to_msm_bo(obj); - struct msm_gem_vma *vma; - - msm_gem_assert_locked(obj); - - list_for_each_entry(vma, &msm_obj->vmas, list) { - if (vma->aspace == aspace) - return vma; + return vma; + } + } } return NULL; } -static void del_vma(struct msm_gem_vma *vma) -{ - if (!vma) - return; - - list_del(&vma->list); - kfree(vma); -} - /* * If close is true, this also closes the VMA (releasing the allocated * iova range) in addition to removing the iommu mapping. In the eviction @@ -446,71 +436,54 @@ static void del_vma(struct msm_gem_vma *vma) * mapping. */ static void -put_iova_spaces(struct drm_gem_object *obj, bool close) +put_iova_spaces(struct drm_gem_object *obj, struct drm_gpuvm *vm, + bool close, const char *reason) { - struct msm_gem_object *msm_obj = to_msm_bo(obj); - struct msm_gem_vma *vma; + struct drm_gpuvm_bo *vm_bo, *tmp; msm_gem_assert_locked(obj); - list_for_each_entry(vma, &msm_obj->vmas, list) { - if (vma->aspace) { - msm_gem_vma_purge(vma); + drm_gem_for_each_gpuvm_bo_safe (vm_bo, tmp, obj) { + struct drm_gpuva *vma, *vmatmp; + + if (vm && vm_bo->vm != vm) + continue; + + drm_gpuvm_bo_get(vm_bo); + + drm_gpuvm_bo_for_each_va_safe (vma, vmatmp, vm_bo) { + msm_gem_vma_unmap(vma, reason); if (close) msm_gem_vma_close(vma); } - } -} -/* Called with msm_obj locked */ -static void -put_iova_vmas(struct drm_gem_object *obj) -{ - struct msm_gem_object *msm_obj = to_msm_bo(obj); - struct msm_gem_vma *vma, *tmp; - - msm_gem_assert_locked(obj); - - list_for_each_entry_safe(vma, tmp, &msm_obj->vmas, list) { - del_vma(vma); + drm_gpuvm_bo_put(vm_bo); } } -static struct msm_gem_vma *get_vma_locked(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, - u64 range_start, u64 range_end) +static struct drm_gpuva *get_vma_locked(struct drm_gem_object *obj, + struct drm_gpuvm *vm, u64 range_start, + u64 range_end) { - struct msm_gem_vma *vma; + struct drm_gpuva *vma; msm_gem_assert_locked(obj); - vma = lookup_vma(obj, aspace); + vma = lookup_vma(obj, vm); if (!vma) { - int ret; - - vma = add_vma(obj, aspace); - if (IS_ERR(vma)) - return vma; - - ret = msm_gem_vma_init(vma, obj->size, - range_start, range_end); - if (ret) { - del_vma(vma); - return ERR_PTR(ret); - } + vma = msm_gem_vma_new(vm, obj, 0, range_start, range_end); } else { - GEM_WARN_ON(vma->iova < range_start); - GEM_WARN_ON((vma->iova + obj->size) > range_end); + GEM_WARN_ON(vma->va.addr < range_start); + GEM_WARN_ON((vma->va.addr + obj->size) > range_end); } return vma; } -int msm_gem_pin_vma_locked(struct drm_gem_object *obj, struct msm_gem_vma *vma) +int msm_gem_prot(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); - struct page **pages; int prot = IOMMU_READ; if (!(msm_obj->flags & MSM_BO_GPU_READONLY)) @@ -522,13 +495,22 @@ int msm_gem_pin_vma_locked(struct drm_gem_object *obj, struct msm_gem_vma *vma) if (msm_obj->flags & MSM_BO_CACHED_COHERENT) prot |= IOMMU_CACHE; + return prot; +} + +int msm_gem_pin_vma_locked(struct drm_gem_object *obj, struct drm_gpuva *vma) +{ + struct msm_gem_object *msm_obj = to_msm_bo(obj); + struct page **pages; + int prot = msm_gem_prot(obj); + msm_gem_assert_locked(obj); pages = msm_gem_get_pages_locked(obj, MSM_MADV_WILLNEED); if (IS_ERR(pages)) return PTR_ERR(pages); - return msm_gem_vma_map(vma, prot, msm_obj->sgt, obj->size); + return msm_gem_vma_map(vma, prot, msm_obj->sgt); } void msm_gem_unpin_locked(struct drm_gem_object *obj) @@ -560,28 +542,31 @@ void msm_gem_unpin_active(struct drm_gem_object *obj) update_lru_active(obj); } -struct msm_gem_vma *msm_gem_get_vma_locked(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace) +struct drm_gpuva *msm_gem_get_vma_locked(struct drm_gem_object *obj, + struct drm_gpuvm *vm) { - return get_vma_locked(obj, aspace, 0, U64_MAX); + return get_vma_locked(obj, vm, 0, U64_MAX); } static int get_and_pin_iova_range_locked(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, uint64_t *iova, - u64 range_start, u64 range_end) + struct drm_gpuvm *vm, uint64_t *iova, + u64 range_start, u64 range_end) { - struct msm_gem_vma *vma; + struct drm_gpuva *vma; int ret; msm_gem_assert_locked(obj); - vma = get_vma_locked(obj, aspace, range_start, range_end); + if (to_msm_bo(obj)->flags & MSM_BO_NO_SHARE) + return -EINVAL; + + vma = get_vma_locked(obj, vm, range_start, range_end); if (IS_ERR(vma)) return PTR_ERR(vma); ret = msm_gem_pin_vma_locked(obj, vma); if (!ret) { - *iova = vma->iova; + *iova = vma->va.addr; pin_obj_locked(obj); } @@ -593,58 +578,59 @@ static int get_and_pin_iova_range_locked(struct drm_gem_object *obj, * limits iova to specified range (in pages) */ int msm_gem_get_and_pin_iova_range(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, uint64_t *iova, - u64 range_start, u64 range_end) + struct drm_gpuvm *vm, uint64_t *iova, + u64 range_start, u64 range_end) { + struct drm_exec exec; int ret; - msm_gem_lock(obj); - ret = get_and_pin_iova_range_locked(obj, aspace, iova, range_start, range_end); - msm_gem_unlock(obj); + msm_gem_lock_vm_and_obj(&exec, obj, vm); + ret = get_and_pin_iova_range_locked(obj, vm, iova, range_start, range_end); + drm_exec_fini(&exec); /* drop locks */ return ret; } /* get iova and pin it. Should have a matching put */ -int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, uint64_t *iova) +int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, struct drm_gpuvm *vm, + uint64_t *iova) { - return msm_gem_get_and_pin_iova_range(obj, aspace, iova, 0, U64_MAX); + return msm_gem_get_and_pin_iova_range(obj, vm, iova, 0, U64_MAX); } /* * Get an iova but don't pin it. Doesn't need a put because iovas are currently * valid for the life of the object */ -int msm_gem_get_iova(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, uint64_t *iova) +int msm_gem_get_iova(struct drm_gem_object *obj, struct drm_gpuvm *vm, + uint64_t *iova) { - struct msm_gem_vma *vma; + struct drm_gpuva *vma; + struct drm_exec exec; int ret = 0; - msm_gem_lock(obj); - vma = get_vma_locked(obj, aspace, 0, U64_MAX); + msm_gem_lock_vm_and_obj(&exec, obj, vm); + vma = get_vma_locked(obj, vm, 0, U64_MAX); if (IS_ERR(vma)) { ret = PTR_ERR(vma); } else { - *iova = vma->iova; + *iova = vma->va.addr; } - msm_gem_unlock(obj); + drm_exec_fini(&exec); /* drop locks */ return ret; } static int clear_iova(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace) + struct drm_gpuvm *vm) { - struct msm_gem_vma *vma = lookup_vma(obj, aspace); + struct drm_gpuva *vma = lookup_vma(obj, vm); if (!vma) return 0; - msm_gem_vma_purge(vma); + msm_gem_vma_unmap(vma, NULL); msm_gem_vma_close(vma); - del_vma(vma); return 0; } @@ -657,51 +643,89 @@ static int clear_iova(struct drm_gem_object *obj, * Setting an iova of zero will clear the vma. */ int msm_gem_set_iova(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, uint64_t iova) + struct drm_gpuvm *vm, uint64_t iova) { + struct drm_exec exec; int ret = 0; - msm_gem_lock(obj); + msm_gem_lock_vm_and_obj(&exec, obj, vm); if (!iova) { - ret = clear_iova(obj, aspace); + ret = clear_iova(obj, vm); } else { - struct msm_gem_vma *vma; - vma = get_vma_locked(obj, aspace, iova, iova + obj->size); + struct drm_gpuva *vma; + vma = get_vma_locked(obj, vm, iova, iova + obj->size); if (IS_ERR(vma)) { ret = PTR_ERR(vma); - } else if (GEM_WARN_ON(vma->iova != iova)) { - clear_iova(obj, aspace); + } else if (GEM_WARN_ON(vma->va.addr != iova)) { + clear_iova(obj, vm); ret = -EBUSY; } } - msm_gem_unlock(obj); + drm_exec_fini(&exec); /* drop locks */ return ret; } +static bool is_kms_vm(struct drm_gpuvm *vm) +{ +#ifdef CONFIG_DRM_MSM_KMS + struct msm_drm_private *priv = vm->drm->dev_private; + + return priv->kms && (priv->kms->vm == vm); +#else + return false; +#endif +} + /* * Unpin a iova by updating the reference counts. The memory isn't actually * purged until something else (shrinker, mm_notifier, destroy, etc) decides * to get rid of it */ -void msm_gem_unpin_iova(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace) +void msm_gem_unpin_iova(struct drm_gem_object *obj, struct drm_gpuvm *vm) { - struct msm_gem_vma *vma; + struct drm_gpuva *vma; + struct drm_exec exec; - msm_gem_lock(obj); - vma = lookup_vma(obj, aspace); - if (!GEM_WARN_ON(!vma)) { + msm_gem_lock_vm_and_obj(&exec, obj, vm); + vma = lookup_vma(obj, vm); + if (vma) { msm_gem_unpin_locked(obj); } - msm_gem_unlock(obj); + if (!is_kms_vm(vm)) + put_iova_spaces(obj, vm, true, "close"); + drm_exec_fini(&exec); /* drop locks */ } int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args) { - args->pitch = align_pitch(args->width, args->bpp); - args->size = PAGE_ALIGN(args->pitch * args->height); + u32 fourcc; + u64 pitch_align; + int ret; + + /* + * Adreno needs pitch aligned to 32 pixels. Compute the number + * of bytes for a block of 32 pixels at the given color format. + * Use the result as pitch alignment. + */ + fourcc = drm_driver_color_mode_format(dev, args->bpp); + if (fourcc != DRM_FORMAT_INVALID) { + const struct drm_format_info *info; + + info = drm_format_info(fourcc); + if (!info) + return -EINVAL; + pitch_align = drm_format_info_min_pitch(info, 0, 32); + } else { + pitch_align = round_up(args->width, 32) * DIV_ROUND_UP(args->bpp, SZ_8); + } + if (!pitch_align || pitch_align > U32_MAX) + return -EINVAL; + ret = drm_mode_size_dumb(dev, args, pitch_align, 0); + if (ret) + return ret; + return msm_gem_new_handle(dev, file, args->size, MSM_BO_SCANOUT | MSM_BO_WC, &args->handle, "dumb"); } @@ -735,7 +759,7 @@ static void *get_vaddr(struct drm_gem_object *obj, unsigned madv) msm_gem_assert_locked(obj); - if (obj->import_attach) + if (drm_gem_is_imported(obj)) return ERR_PTR(-ENODEV); pages = msm_gem_get_pages_locked(obj, madv); @@ -853,7 +877,7 @@ void msm_gem_purge(struct drm_gem_object *obj) GEM_WARN_ON(!is_purgeable(msm_obj)); /* Get rid of any iommu mapping(s): */ - put_iova_spaces(obj, true); + put_iova_spaces(obj, NULL, false, "purge"); msm_gem_vunmap(obj); @@ -861,8 +885,6 @@ void msm_gem_purge(struct drm_gem_object *obj) put_pages(obj); - put_iova_vmas(obj); - mutex_lock(&priv->lru.lock); /* A one-way transition: */ msm_obj->madv = __MSM_MADV_PURGED; @@ -893,7 +915,7 @@ void msm_gem_evict(struct drm_gem_object *obj) GEM_WARN_ON(is_unevictable(msm_obj)); /* Get rid of any iommu mapping(s): */ - put_iova_spaces(obj, false); + put_iova_spaces(obj, NULL, false, "evict"); drm_vma_node_unmap(&obj->vma_node, dev->anon_inode->i_mapping); @@ -920,7 +942,7 @@ bool msm_gem_active(struct drm_gem_object *obj) if (to_msm_bo(obj)->pin_count) return true; - return !dma_resv_test_signaled(obj->resv, dma_resv_usage_rw(true)); + return !dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_BOOKKEEP); } int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) @@ -959,11 +981,11 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m, { struct msm_gem_object *msm_obj = to_msm_bo(obj); struct dma_resv *robj = obj->resv; - struct msm_gem_vma *vma; uint64_t off = drm_vma_node_start(&obj->vma_node); const char *madv; - msm_gem_lock(obj); + if (!msm_gem_trylock(obj)) + return; stats->all.count++; stats->all.size += obj->size; @@ -1002,31 +1024,33 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m, seq_printf(m, " %08zu %9s %-32s\n", obj->size, madv, msm_obj->name); - if (!list_empty(&msm_obj->vmas)) { + if (!list_empty(&obj->gpuva.list)) { + struct drm_gpuvm_bo *vm_bo; seq_puts(m, " vmas:"); - list_for_each_entry(vma, &msm_obj->vmas, list) { - const char *name, *comm; - if (vma->aspace) { - struct msm_gem_address_space *aspace = vma->aspace; + drm_gem_for_each_gpuvm_bo (vm_bo, obj) { + struct drm_gpuva *vma; + + drm_gpuvm_bo_for_each_va (vma, vm_bo) { + const char *name, *comm; + struct msm_gem_vm *vm = to_msm_vm(vma->vm); struct task_struct *task = - get_pid_task(aspace->pid, PIDTYPE_PID); + get_pid_task(vm->pid, PIDTYPE_PID); if (task) { comm = kstrdup(task->comm, GFP_KERNEL); put_task_struct(task); } else { comm = NULL; } - name = aspace->name; - } else { - name = comm = NULL; + name = vm->base.name; + + seq_printf(m, " [%s%s%s: vm=%p, %08llx, %smapped]", + name, comm ? ":" : "", comm ? comm : "", + vma->vm, vma->va.addr, + to_msm_vma(vma)->mapped ? "" : "un"); + kfree(comm); } - seq_printf(m, " [%s%s%s: aspace=%p, %08llx,%s]", - name, comm ? ":" : "", comm ? comm : "", - vma->aspace, vma->iova, - vma->mapped ? "mapped" : "unmapped"); - kfree(comm); } seq_puts(m, "\n"); @@ -1067,14 +1091,48 @@ static void msm_gem_free_object(struct drm_gem_object *obj) struct msm_gem_object *msm_obj = to_msm_bo(obj); struct drm_device *dev = obj->dev; struct msm_drm_private *priv = dev->dev_private; + struct drm_exec exec; mutex_lock(&priv->obj_lock); list_del(&msm_obj->node); mutex_unlock(&priv->obj_lock); - put_iova_spaces(obj, true); + /* + * We need to lock any VMs the object is still attached to, but not + * the object itself (see explaination in msm_gem_assert_locked()), + * so just open-code this special case. + * + * Note that we skip the dance if we aren't attached to any VM. This + * is load bearing. The driver needs to support two usage models: + * + * 1. Legacy kernel managed VM: Userspace expects the VMA's to be + * implicitly torn down when the object is freed, the VMA's do + * not hold a hard reference to the BO. + * + * 2. VM_BIND, userspace managed VM: The VMA holds a reference to the + * BO. This can be dropped when the VM is closed and it's associated + * VMAs are torn down. (See msm_gem_vm_close()). + * + * In the latter case the last reference to a BO can be dropped while + * we already have the VM locked. It would have already been removed + * from the gpuva list, but lockdep doesn't know that. Or understand + * the differences between the two usage models. + */ + if (!list_empty(&obj->gpuva.list)) { + drm_exec_init(&exec, 0, 0); + drm_exec_until_all_locked (&exec) { + struct drm_gpuvm_bo *vm_bo; + drm_gem_for_each_gpuvm_bo (vm_bo, obj) { + drm_exec_lock_obj(&exec, + drm_gpuvm_resv_obj(vm_bo->vm)); + drm_exec_retry_on_contention(&exec); + } + } + put_iova_spaces(obj, NULL, true, "free"); + drm_exec_fini(&exec); /* drop locks */ + } - if (obj->import_attach) { + if (drm_gem_is_imported(obj)) { GEM_WARN_ON(msm_obj->vaddr); /* Don't drop the pages for imported dmabuf, as they are not @@ -1082,13 +1140,24 @@ static void msm_gem_free_object(struct drm_gem_object *obj) */ kvfree(msm_obj->pages); - put_iova_vmas(obj); - drm_prime_gem_destroy(obj, msm_obj->sgt); } else { msm_gem_vunmap(obj); put_pages(obj); - put_iova_vmas(obj); + } + + /* + * In error paths, we could end up here before msm_gem_new_handle() + * has changed obj->resv to point to the shared resv. In this case, + * we don't want to drop a ref to the shared r_obj that we haven't + * taken yet. + */ + if ((msm_obj->flags & MSM_BO_NO_SHARE) && (obj->resv != &obj->_resv)) { + struct drm_gem_object *r_obj = + container_of(obj->resv, struct drm_gem_object, _resv); + + /* Drop reference we hold to shared resv obj: */ + drm_gem_object_put(r_obj); } drm_gem_object_release(obj); @@ -1109,7 +1178,7 @@ static int msm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct /* convenience method to construct a GEM buffer object, and userspace handle */ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, - uint32_t size, uint32_t flags, uint32_t *handle, + size_t size, uint32_t flags, uint32_t *handle, char *name) { struct drm_gem_object *obj; @@ -1123,6 +1192,15 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, if (name) msm_gem_object_set_name(obj, "%s", name); + if (flags & MSM_BO_NO_SHARE) { + struct msm_context *ctx = file->driver_priv; + struct drm_gem_object *r_obj = drm_gpuvm_resv_obj(ctx->vm); + + drm_gem_object_get(r_obj); + + obj->resv = r_obj->resv; + } + ret = drm_gem_handle_create(file, obj, handle); /* drop reference from allocate - handle holds it now */ @@ -1155,6 +1233,7 @@ static const struct drm_gem_object_funcs msm_gem_object_funcs = { .free = msm_gem_free_object, .open = msm_gem_open, .close = msm_gem_close, + .export = msm_gem_prime_export, .pin = msm_gem_prime_pin, .unpin = msm_gem_prime_unpin, .get_sg_table = msm_gem_prime_get_sg_table, @@ -1165,9 +1244,8 @@ static const struct drm_gem_object_funcs msm_gem_object_funcs = { .vm_ops = &vm_ops, }; -static int msm_gem_new_impl(struct drm_device *dev, - uint32_t size, uint32_t flags, - struct drm_gem_object **obj) +static int msm_gem_new_impl(struct drm_device *dev, uint32_t flags, + struct drm_gem_object **obj) { struct msm_drm_private *priv = dev->dev_private; struct msm_gem_object *msm_obj; @@ -1194,7 +1272,6 @@ static int msm_gem_new_impl(struct drm_device *dev, msm_obj->madv = MSM_MADV_WILLNEED; INIT_LIST_HEAD(&msm_obj->node); - INIT_LIST_HEAD(&msm_obj->vmas); *obj = &msm_obj->base; (*obj)->funcs = &msm_gem_object_funcs; @@ -1202,74 +1279,37 @@ static int msm_gem_new_impl(struct drm_device *dev, return 0; } -struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32_t flags) +struct drm_gem_object *msm_gem_new(struct drm_device *dev, size_t size, uint32_t flags) { struct msm_drm_private *priv = dev->dev_private; struct msm_gem_object *msm_obj; struct drm_gem_object *obj = NULL; - bool use_vram = false; int ret; size = PAGE_ALIGN(size); - if (!msm_use_mmu(dev)) - use_vram = true; - else if ((flags & (MSM_BO_STOLEN | MSM_BO_SCANOUT)) && priv->vram.size) - use_vram = true; - - if (GEM_WARN_ON(use_vram && !priv->vram.size)) - return ERR_PTR(-EINVAL); - /* Disallow zero sized objects as they make the underlying * infrastructure grumpy */ if (size == 0) return ERR_PTR(-EINVAL); - ret = msm_gem_new_impl(dev, size, flags, &obj); + ret = msm_gem_new_impl(dev, flags, &obj); if (ret) return ERR_PTR(ret); msm_obj = to_msm_bo(obj); - if (use_vram) { - struct msm_gem_vma *vma; - struct page **pages; - - drm_gem_private_object_init(dev, obj, size); - - msm_gem_lock(obj); - - vma = add_vma(obj, NULL); - msm_gem_unlock(obj); - if (IS_ERR(vma)) { - ret = PTR_ERR(vma); - goto fail; - } - - to_msm_bo(obj)->vram_node = &vma->node; - - msm_gem_lock(obj); - pages = get_pages(obj); - msm_gem_unlock(obj); - if (IS_ERR(pages)) { - ret = PTR_ERR(pages); - goto fail; - } - - vma->iova = physaddr(obj); - } else { - ret = drm_gem_object_init(dev, obj, size); - if (ret) - goto fail; - /* - * Our buffers are kept pinned, so allocating them from the - * MOVABLE zone is a really bad idea, and conflicts with CMA. - * See comments above new_inode() why this is required _and_ - * expected if you're going to pin these pages. - */ - mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER); - } + ret = drm_gem_object_init(dev, obj, size); + if (ret) + goto fail; + /* + * Our buffers are kept pinned, so allocating them from the + * MOVABLE zone is a really bad idea, and conflicts with CMA. + * See comments above new_inode() why this is required _and_ + * expected if you're going to pin these pages. + */ + mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER); drm_gem_lru_move_tail(&priv->lru.unbacked, obj); @@ -1294,18 +1334,12 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev, struct msm_drm_private *priv = dev->dev_private; struct msm_gem_object *msm_obj; struct drm_gem_object *obj; - uint32_t size; - int ret, npages; - - /* if we don't have IOMMU, don't bother pretending we can import: */ - if (!msm_use_mmu(dev)) { - DRM_DEV_ERROR(dev->dev, "cannot import without IOMMU\n"); - return ERR_PTR(-EINVAL); - } + size_t size, npages; + int ret; size = PAGE_ALIGN(dmabuf->size); - ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj); + ret = msm_gem_new_impl(dev, MSM_BO_WC, &obj); if (ret) return ERR_PTR(ret); @@ -1348,9 +1382,9 @@ fail: return ERR_PTR(ret); } -void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size, - uint32_t flags, struct msm_gem_address_space *aspace, - struct drm_gem_object **bo, uint64_t *iova) +void *msm_gem_kernel_new(struct drm_device *dev, size_t size, uint32_t flags, + struct drm_gpuvm *vm, struct drm_gem_object **bo, + uint64_t *iova) { void *vaddr; struct drm_gem_object *obj = msm_gem_new(dev, size, flags); @@ -1360,14 +1394,14 @@ void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size, return ERR_CAST(obj); if (iova) { - ret = msm_gem_get_and_pin_iova(obj, aspace, iova); + ret = msm_gem_get_and_pin_iova(obj, vm, iova); if (ret) goto err; } vaddr = msm_gem_get_vaddr(obj); if (IS_ERR(vaddr)) { - msm_gem_unpin_iova(obj, aspace); + msm_gem_unpin_iova(obj, vm); ret = PTR_ERR(vaddr); goto err; } @@ -1383,14 +1417,13 @@ err: } -void msm_gem_kernel_put(struct drm_gem_object *bo, - struct msm_gem_address_space *aspace) +void msm_gem_kernel_put(struct drm_gem_object *bo, struct drm_gpuvm *vm) { if (IS_ERR_OR_NULL(bo)) return; msm_gem_put_vaddr(bo); - msm_gem_unpin_iova(bo, aspace); + msm_gem_unpin_iova(bo, vm); drm_gem_object_put(bo); } diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 85f0257e83da..a4cf31853c50 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -7,9 +7,11 @@ #ifndef __MSM_GEM_H__ #define __MSM_GEM_H__ +#include "msm_mmu.h" #include <linux/kref.h> #include <linux/dma-resv.h> #include "drm/drm_exec.h" +#include "drm/drm_gpuvm.h" #include "drm/gpu_scheduler.h" #include "msm_drv.h" @@ -22,56 +24,173 @@ #define MSM_BO_STOLEN 0x10000000 /* try to use stolen/splash memory */ #define MSM_BO_MAP_PRIV 0x20000000 /* use IOMMU_PRIV when mapping */ -struct msm_gem_address_space { - const char *name; - /* NOTE: mm managed at the page level, size is in # of pages - * and position mm_node->start is in # of pages: +/** + * struct msm_gem_vm_log_entry - An entry in the VM log + * + * For userspace managed VMs, a log of recent VM updates is tracked and + * captured in GPU devcore dumps, to aid debugging issues caused by (for + * example) incorrectly synchronized VM updates + */ +struct msm_gem_vm_log_entry { + const char *op; + uint64_t iova; + uint64_t range; + int queue_id; +}; + +/** + * struct msm_gem_vm - VM object + * + * A VM object representing a GPU (or display or GMU or ...) virtual address + * space. + * + * In the case of GPU, if per-process address spaces are supported, the address + * space is split into two VMs, which map to TTBR0 and TTBR1 in the SMMU. TTBR0 + * is used for userspace objects, and is unique per msm_context/drm_file, while + * TTBR1 is the same for all processes. (The kernel controlled ringbuffer and + * a few other kernel controlled buffers live in TTBR1.) + * + * The GPU TTBR0 vm can be managed by userspace or by the kernel, depending on + * whether userspace supports VM_BIND. All other vm's are managed by the kernel. + * (Managed by kernel means the kernel is responsible for VA allocation.) + * + * Note that because VM_BIND allows a given BO to be mapped multiple times in + * a VM, and therefore have multiple VMA's in a VM, there is an extra object + * provided by drm_gpuvm infrastructure.. the drm_gpuvm_bo, which is not + * embedded in any larger driver structure. The GEM object holds a list of + * drm_gpuvm_bo, which in turn holds a list of msm_gem_vma. A linked vma + * holds a reference to the vm_bo, and drops it when the vma is unlinked. + * So we just need to call drm_gpuvm_bo_obtain() to return a ref to an + * existing vm_bo, or create a new one. Once the vma is linked, the ref + * to the vm_bo can be dropped (since the vma is holding one). + */ +struct msm_gem_vm { + /** @base: Inherit from drm_gpuvm. */ + struct drm_gpuvm base; + + /** + * @sched: Scheduler used for asynchronous VM_BIND request. + * + * Unused for kernel managed VMs (where all operations are synchronous). + */ + struct drm_gpu_scheduler sched; + + /** + * @prealloc_throttle: Used to throttle VM_BIND ops if too much pre- + * allocated memory is in flight. + * + * Because we have to pre-allocate pgtable pages for the worst case + * (ie. new mappings do not share any PTEs with existing mappings) + * we could end up consuming a lot of resources transiently. The + * prealloc_throttle puts an upper bound on that. + */ + struct { + /** @wait: Notified when preallocated resources are released */ + wait_queue_head_t wait; + + /** + * @in_flight: The # of preallocated pgtable pages in-flight + * for queued VM_BIND jobs. + */ + atomic_t in_flight; + } prealloc_throttle; + + /** + * @mm: Memory management for kernel managed VA allocations + * + * Only used for kernel managed VMs, unused for user managed VMs. + * + * Protected by vm lock. See msm_gem_lock_vm_and_obj(), for ex. */ struct drm_mm mm; - spinlock_t lock; /* Protects drm_mm node allocation/removal */ + + /** @mmu: The mmu object which manages the pgtables */ struct msm_mmu *mmu; - struct kref kref; - /* For address spaces associated with a specific process, this + /** @mmu_lock: Protects access to the mmu */ + struct mutex mmu_lock; + + /** + * @pid: For address spaces associated with a specific process, this * will be non-NULL: */ struct pid *pid; - /* @faults: the number of GPU hangs associated with this address space */ + /** @last_fence: Fence for last pending work scheduled on the VM */ + struct dma_fence *last_fence; + + /** @log: A log of recent VM updates */ + struct msm_gem_vm_log_entry *log; + + /** @log_shift: length of @log is (1 << @log_shift) */ + uint32_t log_shift; + + /** @log_idx: index of next @log entry to write */ + uint32_t log_idx; + + /** @faults: the number of GPU hangs associated with this address space */ int faults; - /** @va_start: lowest possible address to allocate */ - uint64_t va_start; + /** @managed: is this a kernel managed VM? */ + bool managed; - /** @va_size: the size of the address space (in bytes) */ - uint64_t va_size; + /** + * @unusable: True if the VM has turned unusable because something + * bad happened during an asynchronous request. + * + * We don't try to recover from such failures, because this implies + * informing userspace about the specific operation that failed, and + * hoping the userspace driver can replay things from there. This all + * sounds very complicated for little gain. + * + * Instead, we should just flag the VM as unusable, and fail any + * further request targeting this VM. + * + * As an analogy, this would be mapped to a VK_ERROR_DEVICE_LOST + * situation, where the logical device needs to be re-created. + */ + bool unusable; }; +#define to_msm_vm(x) container_of(x, struct msm_gem_vm, base) -struct msm_gem_address_space * -msm_gem_address_space_get(struct msm_gem_address_space *aspace); - -void msm_gem_address_space_put(struct msm_gem_address_space *aspace); +struct drm_gpuvm * +msm_gem_vm_create(struct drm_device *drm, struct msm_mmu *mmu, const char *name, + u64 va_start, u64 va_size, bool managed); -struct msm_gem_address_space * -msm_gem_address_space_create(struct msm_mmu *mmu, const char *name, - u64 va_start, u64 size); +void msm_gem_vm_close(struct drm_gpuvm *gpuvm); +void msm_gem_vm_unusable(struct drm_gpuvm *gpuvm); struct msm_fence_context; +#define MSM_VMA_DUMP (DRM_GPUVA_USERBITS << 0) + +/** + * struct msm_gem_vma - a VMA mapping + * + * Represents a combination of a GEM object plus a VM. + */ struct msm_gem_vma { + /** @base: inherit from drm_gpuva */ + struct drm_gpuva base; + + /** + * @node: mm node for VA allocation + * + * Only used by kernel managed VMs + */ struct drm_mm_node node; - uint64_t iova; - struct msm_gem_address_space *aspace; - struct list_head list; /* node in msm_gem_object::vmas */ + + /** @mapped: Is this VMA mapped? */ bool mapped; }; +#define to_msm_vma(x) container_of(x, struct msm_gem_vma, base) -struct msm_gem_vma *msm_gem_vma_new(struct msm_gem_address_space *aspace); -int msm_gem_vma_init(struct msm_gem_vma *vma, int size, - u64 range_start, u64 range_end); -void msm_gem_vma_purge(struct msm_gem_vma *vma); -int msm_gem_vma_map(struct msm_gem_vma *vma, int prot, struct sg_table *sgt, int size); -void msm_gem_vma_close(struct msm_gem_vma *vma); +struct drm_gpuva * +msm_gem_vma_new(struct drm_gpuvm *vm, struct drm_gem_object *obj, + u64 offset, u64 range_start, u64 range_end); +void msm_gem_vma_unmap(struct drm_gpuva *vma, const char *reason); +int msm_gem_vma_map(struct drm_gpuva *vma, int prot, struct sg_table *sgt); +void msm_gem_vma_close(struct drm_gpuva *vma); struct msm_gem_object { struct drm_gem_object base; @@ -100,13 +219,6 @@ struct msm_gem_object { struct sg_table *sgt; void *vaddr; - struct list_head vmas; /* list of msm_gem_vma */ - - /* For physically contiguous buffers. Used when we don't have - * an IOMMU. Also used for stolen/splashscreen buffer. - */ - struct drm_mm_node *vram_node; - char name[32]; /* Identifier to print for the debugfs files */ /* userspace metadata backchannel */ @@ -119,27 +231,56 @@ struct msm_gem_object { * Protected by LRU lock. */ int pin_count; + + /** + * @vma_ref: Reference count of VMA users. + * + * With the vm_bo/vma holding a reference to the GEM object, we'd + * otherwise have to actively tear down a VMA when, for example, + * a buffer is unpinned for scanout, vs. the pre-drm_gpuvm approach + * where a VMA did not hold a reference to the BO, but instead was + * implicitly torn down when the BO was freed. + * + * To regain the lazy VMA teardown, we use the @vma_ref. It is + * incremented for any of the following: + * + * 1) the BO is exported as a dma_buf + * 2) the BO has open userspace handle + * + * All of those conditions will hold an reference to the BO, + * preventing it from being freed. So lazily keeping around the + * VMA will not prevent the BO from being freed. (Or rather, the + * reference loop is harmless in this case.) + * + * When the @vma_ref drops to zero, then kms->vm VMA will be + * torn down. + */ + atomic_t vma_ref; }; #define to_msm_bo(x) container_of(x, struct msm_gem_object, base) +void msm_gem_vma_get(struct drm_gem_object *obj); +void msm_gem_vma_put(struct drm_gem_object *obj); + uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj); -int msm_gem_pin_vma_locked(struct drm_gem_object *obj, struct msm_gem_vma *vma); +int msm_gem_prot(struct drm_gem_object *obj); +int msm_gem_pin_vma_locked(struct drm_gem_object *obj, struct drm_gpuva *vma); void msm_gem_unpin_locked(struct drm_gem_object *obj); void msm_gem_unpin_active(struct drm_gem_object *obj); -struct msm_gem_vma *msm_gem_get_vma_locked(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace); -int msm_gem_get_iova(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, uint64_t *iova); -int msm_gem_set_iova(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, uint64_t iova); +struct drm_gpuva *msm_gem_get_vma_locked(struct drm_gem_object *obj, + struct drm_gpuvm *vm); +int msm_gem_get_iova(struct drm_gem_object *obj, struct drm_gpuvm *vm, + uint64_t *iova); +int msm_gem_set_iova(struct drm_gem_object *obj, struct drm_gpuvm *vm, + uint64_t iova); int msm_gem_get_and_pin_iova_range(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, uint64_t *iova, - u64 range_start, u64 range_end); -int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, uint64_t *iova); -void msm_gem_unpin_iova(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace); + struct drm_gpuvm *vm, uint64_t *iova, + u64 range_start, u64 range_end); +int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, struct drm_gpuvm *vm, + uint64_t *iova); +void msm_gem_unpin_iova(struct drm_gem_object *obj, struct drm_gpuvm *vm); void msm_gem_pin_obj_locked(struct drm_gem_object *obj); +struct page **msm_gem_get_pages_locked(struct drm_gem_object *obj, unsigned madv); struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj); void msm_gem_unpin_pages_locked(struct drm_gem_object *obj); int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev, @@ -156,14 +297,13 @@ bool msm_gem_active(struct drm_gem_object *obj); int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); int msm_gem_cpu_fini(struct drm_gem_object *obj); int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, - uint32_t size, uint32_t flags, uint32_t *handle, char *name); + size_t size, uint32_t flags, uint32_t *handle, char *name); struct drm_gem_object *msm_gem_new(struct drm_device *dev, - uint32_t size, uint32_t flags); -void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size, - uint32_t flags, struct msm_gem_address_space *aspace, - struct drm_gem_object **bo, uint64_t *iova); -void msm_gem_kernel_put(struct drm_gem_object *bo, - struct msm_gem_address_space *aspace); + size_t size, uint32_t flags); +void *msm_gem_kernel_new(struct drm_device *dev, size_t size, uint32_t flags, + struct drm_gpuvm *vm, struct drm_gem_object **bo, + uint64_t *iova); +void msm_gem_kernel_put(struct drm_gem_object *bo, struct drm_gpuvm *vm); struct drm_gem_object *msm_gem_import(struct drm_device *dev, struct dma_buf *dmabuf, struct sg_table *sgt); __printf(2, 3) @@ -188,6 +328,12 @@ msm_gem_lock(struct drm_gem_object *obj) dma_resv_lock(obj->resv, NULL); } +static inline bool __must_check +msm_gem_trylock(struct drm_gem_object *obj) +{ + return dma_resv_trylock(obj->resv); +} + static inline int msm_gem_lock_interruptible(struct drm_gem_object *obj) { @@ -200,6 +346,37 @@ msm_gem_unlock(struct drm_gem_object *obj) dma_resv_unlock(obj->resv); } +/** + * msm_gem_lock_vm_and_obj() - Helper to lock an obj + VM + * @exec: the exec context helper which will be initalized + * @obj: the GEM object to lock + * @vm: the VM to lock + * + * Operations which modify a VM frequently need to lock both the VM and + * the object being mapped/unmapped/etc. This helper uses drm_exec to + * acquire both locks, dealing with potential deadlock/backoff scenarios + * which arise when multiple locks are involved. + */ +static inline int +msm_gem_lock_vm_and_obj(struct drm_exec *exec, + struct drm_gem_object *obj, + struct drm_gpuvm *vm) +{ + int ret = 0; + + drm_exec_init(exec, 0, 2); + drm_exec_until_all_locked (exec) { + ret = drm_exec_lock_obj(exec, drm_gpuvm_resv_obj(vm)); + if (!ret && (obj->resv != drm_gpuvm_resv(vm))) + ret = drm_exec_lock_obj(exec, obj); + drm_exec_retry_on_contention(exec); + if (GEM_WARN_ON(ret)) + break; + } + + return ret; +} + static inline void msm_gem_assert_locked(struct drm_gem_object *obj) { @@ -224,7 +401,7 @@ msm_gem_assert_locked(struct drm_gem_object *obj) /* imported/exported objects are not purgeable: */ static inline bool is_unpurgeable(struct msm_gem_object *msm_obj) { - return msm_obj->base.import_attach || msm_obj->pin_count; + return drm_gem_is_imported(&msm_obj->base) || msm_obj->pin_count; } static inline bool is_purgeable(struct msm_gem_object *msm_obj) @@ -257,7 +434,7 @@ struct msm_gem_submit { struct kref ref; struct drm_device *dev; struct msm_gpu *gpu; - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; struct list_head node; /* node in ring submit list */ struct drm_exec exec; uint32_t seqno; /* Sequence number of the submit on the ring */ @@ -297,6 +474,7 @@ struct msm_gem_submit { struct drm_gem_object *obj; uint32_t handle; }; + struct drm_gpuvm_bo *vm_bo; uint64_t iova; } bos[]; }; @@ -320,14 +498,4 @@ static inline void msm_gem_submit_put(struct msm_gem_submit *submit) void msm_submit_retire(struct msm_gem_submit *submit); -/* helper to determine of a buffer in submit should be dumped, used for both - * devcoredump and debugfs cmdstream dumping: - */ -static inline bool -should_dump(struct msm_gem_submit *submit, int idx) -{ - extern bool rd_full; - return rd_full || (submit->bos[idx].flags & MSM_SUBMIT_BO_DUMP); -} - #endif /* __MSM_GEM_H__ */ diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c index ee267490c935..036d34c674d9 100644 --- a/drivers/gpu/drm/msm/msm_gem_prime.c +++ b/drivers/gpu/drm/msm/msm_gem_prime.c @@ -6,6 +6,7 @@ #include <linux/dma-buf.h> +#include <drm/drm_drv.h> #include <drm/drm_prime.h> #include "msm_drv.h" @@ -14,7 +15,10 @@ struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); - int npages = obj->size >> PAGE_SHIFT; + size_t npages = obj->size >> PAGE_SHIFT; + + if (msm_obj->flags & MSM_BO_NO_SHARE) + return ERR_PTR(-EINVAL); if (WARN_ON(!msm_obj->pages)) /* should have already pinned! */ return ERR_PTR(-ENOMEM); @@ -39,20 +43,81 @@ void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map) msm_gem_put_vaddr_locked(obj); } +static void msm_gem_dmabuf_release(struct dma_buf *dma_buf) +{ + struct drm_gem_object *obj = dma_buf->priv; + + msm_gem_vma_put(obj); + drm_gem_dmabuf_release(dma_buf); +} + +static const struct dma_buf_ops msm_gem_prime_dmabuf_ops = { + .attach = drm_gem_map_attach, + .detach = drm_gem_map_detach, + .map_dma_buf = drm_gem_map_dma_buf, + .unmap_dma_buf = drm_gem_unmap_dma_buf, + .release = msm_gem_dmabuf_release, + .mmap = drm_gem_dmabuf_mmap, + .vmap = drm_gem_dmabuf_vmap, + .vunmap = drm_gem_dmabuf_vunmap, +}; + +struct drm_gem_object *msm_gem_prime_import(struct drm_device *dev, + struct dma_buf *buf) +{ + if (buf->ops == &msm_gem_prime_dmabuf_ops) { + struct drm_gem_object *obj = buf->priv; + if (obj->dev == dev) { + /* + * Importing dmabuf exported from our own gem increases + * refcount on gem itself instead of f_count of dmabuf. + */ + drm_gem_object_get(obj); + return obj; + } + } + + return drm_gem_prime_import(dev, buf); +} + struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sg) { return msm_gem_import(dev, attach->dmabuf, sg); } +struct dma_buf *msm_gem_prime_export(struct drm_gem_object *obj, int flags) +{ + if (to_msm_bo(obj)->flags & MSM_BO_NO_SHARE) + return ERR_PTR(-EPERM); + + msm_gem_vma_get(obj); + + struct drm_device *dev = obj->dev; + struct dma_buf_export_info exp_info = { + .exp_name = KBUILD_MODNAME, /* white lie for debug */ + .owner = dev->driver->fops->owner, + .ops = &msm_gem_prime_dmabuf_ops, + .size = obj->size, + .flags = flags, + .priv = obj, + .resv = obj->resv, + }; + + return drm_gem_dmabuf_export(dev, &exp_info); +} + int msm_gem_prime_pin(struct drm_gem_object *obj) { struct page **pages; int ret = 0; - if (obj->import_attach) + if (drm_gem_is_imported(obj)) return 0; + if (to_msm_bo(obj)->flags & MSM_BO_NO_SHARE) + return -EINVAL; + pages = msm_gem_pin_pages_locked(obj); if (IS_ERR(pages)) ret = PTR_ERR(pages); @@ -62,7 +127,7 @@ int msm_gem_prime_pin(struct drm_gem_object *obj) void msm_gem_prime_unpin(struct drm_gem_object *obj) { - if (obj->import_attach) + if (drm_gem_is_imported(obj)) return; msm_gem_unpin_pages_locked(obj); diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index 07ca4ddfe4e3..1039e3c0a47b 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c @@ -44,7 +44,76 @@ msm_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) } static bool -purge(struct drm_gem_object *obj) +with_vm_locks(struct ww_acquire_ctx *ticket, + void (*fn)(struct drm_gem_object *obj), + struct drm_gem_object *obj) +{ + /* + * Track last locked entry for for unwinding locks in error and + * success paths + */ + struct drm_gpuvm_bo *vm_bo, *last_locked = NULL; + int ret = 0; + + drm_gem_for_each_gpuvm_bo (vm_bo, obj) { + struct dma_resv *resv = drm_gpuvm_resv(vm_bo->vm); + + if (resv == obj->resv) + continue; + + ret = dma_resv_lock(resv, ticket); + + /* + * Since we already skip the case when the VM and obj + * share a resv (ie. _NO_SHARE objs), we don't expect + * to hit a double-locking scenario... which the lock + * unwinding cannot really cope with. + */ + WARN_ON(ret == -EALREADY); + + /* + * Don't bother with slow-lock / backoff / retry sequence, + * if we can't get the lock just give up and move on to + * the next object. + */ + if (ret) + goto out_unlock; + + /* + * Hold a ref to prevent the vm_bo from being freed + * and removed from the obj's gpuva list, as that would + * would result in missing the unlock below + */ + drm_gpuvm_bo_get(vm_bo); + + last_locked = vm_bo; + } + + fn(obj); + +out_unlock: + if (last_locked) { + drm_gem_for_each_gpuvm_bo (vm_bo, obj) { + struct dma_resv *resv = drm_gpuvm_resv(vm_bo->vm); + + if (resv == obj->resv) + continue; + + dma_resv_unlock(resv); + + /* Drop the ref taken while locking: */ + drm_gpuvm_bo_put(vm_bo); + + if (last_locked == vm_bo) + break; + } + } + + return ret == 0; +} + +static bool +purge(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket) { if (!is_purgeable(to_msm_bo(obj))) return false; @@ -52,13 +121,11 @@ purge(struct drm_gem_object *obj) if (msm_gem_active(obj)) return false; - msm_gem_purge(obj); - - return true; + return with_vm_locks(ticket, msm_gem_purge, obj); } static bool -evict(struct drm_gem_object *obj) +evict(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket) { if (is_unevictable(to_msm_bo(obj))) return false; @@ -66,43 +133,42 @@ evict(struct drm_gem_object *obj) if (msm_gem_active(obj)) return false; - msm_gem_evict(obj); - - return true; + return with_vm_locks(ticket, msm_gem_evict, obj); } static bool wait_for_idle(struct drm_gem_object *obj) { - enum dma_resv_usage usage = dma_resv_usage_rw(true); + enum dma_resv_usage usage = DMA_RESV_USAGE_BOOKKEEP; return dma_resv_wait_timeout(obj->resv, usage, false, 10) > 0; } static bool -active_purge(struct drm_gem_object *obj) +active_purge(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket) { if (!wait_for_idle(obj)) return false; - return purge(obj); + return purge(obj, ticket); } static bool -active_evict(struct drm_gem_object *obj) +active_evict(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket) { if (!wait_for_idle(obj)) return false; - return evict(obj); + return evict(obj, ticket); } static unsigned long msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) { struct msm_drm_private *priv = shrinker->private_data; + struct ww_acquire_ctx ticket; struct { struct drm_gem_lru *lru; - bool (*shrink)(struct drm_gem_object *obj); + bool (*shrink)(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket); bool cond; unsigned long freed; unsigned long remaining; @@ -122,8 +188,9 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) continue; stages[i].freed = drm_gem_lru_scan(stages[i].lru, nr, - &stages[i].remaining, - stages[i].shrink); + &stages[i].remaining, + stages[i].shrink, + &ticket); nr -= stages[i].freed; freed += stages[i].freed; remaining += stages[i].remaining; @@ -164,7 +231,7 @@ msm_gem_shrinker_shrink(struct drm_device *dev, unsigned long nr_to_scan) static const int vmap_shrink_limit = 15; static bool -vmap_shrink(struct drm_gem_object *obj) +vmap_shrink(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket) { if (!is_vunmapable(to_msm_bo(obj))) return false; @@ -192,7 +259,8 @@ msm_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr) unmapped += drm_gem_lru_scan(lrus[idx], vmap_shrink_limit - unmapped, &remaining, - vmap_shrink); + vmap_shrink, + NULL); } *(unsigned long *)ptr += unmapped; diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index fba78193127d..75d9f3574370 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -4,6 +4,7 @@ * Author: Rob Clark <robdclark@gmail.com> */ +#include <linux/dma-fence-unwrap.h> #include <linux/file.h> #include <linux/sync_file.h> #include <linux/uaccess.h> @@ -16,12 +17,13 @@ #include "msm_gpu.h" #include "msm_gem.h" #include "msm_gpu_trace.h" +#include "msm_syncobj.h" /* For userspace errors, use DRM_UT_DRIVER.. so that userspace can enable * error msgs for debugging, but we don't spam dmesg by default */ -#define SUBMIT_ERROR(submit, fmt, ...) \ - DRM_DEV_DEBUG_DRIVER((submit)->dev->dev, fmt, ##__VA_ARGS__) +#define SUBMIT_ERROR(err, submit, fmt, ...) \ + UERR(err, (submit)->dev, fmt, ##__VA_ARGS__) /* * Cmdstream submission: @@ -30,7 +32,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, struct msm_gpu *gpu, struct msm_gpu_submitqueue *queue, uint32_t nr_bos, - uint32_t nr_cmds) + uint32_t nr_cmds, u64 drm_client_id) { static atomic_t ident = ATOMIC_INIT(0); struct msm_gem_submit *submit; @@ -54,7 +56,8 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, return ERR_PTR(ret); } - ret = drm_sched_job_init(&submit->base, queue->entity, 1, queue); + ret = drm_sched_job_init(&submit->base, queue->entity, 1, queue, + drm_client_id); if (ret) { kfree(submit->hw_fence); kfree(submit); @@ -63,7 +66,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, kref_init(&submit->ref); submit->dev = dev; - submit->aspace = queue->ctx->aspace; + submit->vm = msm_context_vm(dev, queue->ctx); submit->gpu = gpu; submit->cmd = (void *)&submit->bos[nr_bos]; submit->queue = queue; @@ -85,6 +88,15 @@ void __msm_gem_submit_destroy(struct kref *kref) container_of(kref, struct msm_gem_submit, ref); unsigned i; + /* + * In error paths, we could unref the submit without calling + * drm_sched_entity_push_job(), so msm_job_free() will never + * get called. Since drm_sched_job_cleanup() will NULL out + * s_fence, we can use that to detect this case. + */ + if (submit->base.s_fence) + drm_sched_job_cleanup(&submit->base); + if (submit->fence_id) { spin_lock(&submit->queue->idr_lock); idr_remove(&submit->queue->fence_idr, submit->fence_id); @@ -142,8 +154,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, if ((submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) || !(submit_bo.flags & MANDATORY_FLAGS)) { - SUBMIT_ERROR(submit, "invalid flags: %x\n", submit_bo.flags); - ret = -EINVAL; + ret = SUBMIT_ERROR(EINVAL, submit, "invalid flags: %x\n", submit_bo.flags); i = 0; goto out; } @@ -162,8 +173,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, */ obj = idr_find(&file->object_idr, submit->bos[i].handle); if (!obj) { - SUBMIT_ERROR(submit, "invalid handle %u at index %u\n", submit->bos[i].handle, i); - ret = -EINVAL; + ret = SUBMIT_ERROR(EINVAL, submit, "invalid handle %u at index %u\n", submit->bos[i].handle, i); goto out_unlock; } @@ -184,6 +194,7 @@ out: static int submit_lookup_cmds(struct msm_gem_submit *submit, struct drm_msm_gem_submit *args, struct drm_file *file) { + struct msm_context *ctx = file->driver_priv; unsigned i; size_t sz; int ret = 0; @@ -206,17 +217,29 @@ static int submit_lookup_cmds(struct msm_gem_submit *submit, case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: break; default: - SUBMIT_ERROR(submit, "invalid type: %08x\n", submit_cmd.type); - return -EINVAL; + return SUBMIT_ERROR(EINVAL, submit, "invalid type: %08x\n", submit_cmd.type); } if (submit_cmd.size % 4) { - SUBMIT_ERROR(submit, "non-aligned cmdstream buffer size: %u\n", - submit_cmd.size); - ret = -EINVAL; + ret = SUBMIT_ERROR(EINVAL, submit, "non-aligned cmdstream buffer size: %u\n", + submit_cmd.size); goto out; } + if (msm_context_is_vmbind(ctx)) { + if (submit_cmd.nr_relocs) { + ret = SUBMIT_ERROR(EINVAL, submit, "nr_relocs must be zero"); + goto out; + } + + if (submit_cmd.submit_idx || submit_cmd.submit_offset) { + ret = SUBMIT_ERROR(EINVAL, submit, "submit_idx/offset must be zero"); + goto out; + } + + submit->cmd[i].iova = submit_cmd.iova; + } + submit->cmd[i].type = submit_cmd.type; submit->cmd[i].size = submit_cmd.size / 4; submit->cmd[i].offset = submit_cmd.submit_offset / 4; @@ -248,26 +271,55 @@ out: return ret; } +static int submit_lock_objects_vmbind(struct msm_gem_submit *submit) +{ + unsigned flags = DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES; + struct drm_exec *exec = &submit->exec; + int ret = 0; + + drm_exec_init(&submit->exec, flags, submit->nr_bos); + + drm_exec_until_all_locked (&submit->exec) { + ret = drm_gpuvm_prepare_vm(submit->vm, exec, 1); + drm_exec_retry_on_contention(exec); + if (ret) + break; + + ret = drm_gpuvm_prepare_objects(submit->vm, exec, 1); + drm_exec_retry_on_contention(exec); + if (ret) + break; + } + + return ret; +} + /* This is where we make sure all the bo's are reserved and pin'd: */ static int submit_lock_objects(struct msm_gem_submit *submit) { - int ret; + unsigned flags = DRM_EXEC_INTERRUPTIBLE_WAIT; + int ret = 0; - drm_exec_init(&submit->exec, DRM_EXEC_INTERRUPTIBLE_WAIT, submit->nr_bos); + if (msm_context_is_vmbind(submit->queue->ctx)) + return submit_lock_objects_vmbind(submit); + + drm_exec_init(&submit->exec, flags, submit->nr_bos); drm_exec_until_all_locked (&submit->exec) { + ret = drm_exec_lock_obj(&submit->exec, + drm_gpuvm_resv_obj(submit->vm)); + drm_exec_retry_on_contention(&submit->exec); + if (ret) + break; for (unsigned i = 0; i < submit->nr_bos; i++) { struct drm_gem_object *obj = submit->bos[i].obj; ret = drm_exec_prepare_obj(&submit->exec, obj, 1); drm_exec_retry_on_contention(&submit->exec); if (ret) - goto error; + break; } } - return 0; - -error: return ret; } @@ -303,10 +355,10 @@ static int submit_pin_objects(struct msm_gem_submit *submit) for (i = 0; i < submit->nr_bos; i++) { struct drm_gem_object *obj = submit->bos[i].obj; - struct msm_gem_vma *vma; + struct drm_gpuva *vma; /* if locking succeeded, pin bo: */ - vma = msm_gem_get_vma_locked(obj, submit->aspace); + vma = msm_gem_get_vma_locked(obj, submit->vm); if (IS_ERR(vma)) { ret = PTR_ERR(vma); break; @@ -316,7 +368,8 @@ static int submit_pin_objects(struct msm_gem_submit *submit) if (ret) break; - submit->bos[i].iova = vma->iova; + submit->bos[i].vm_bo = drm_gpuvm_bo_get(vma->vm_bo); + submit->bos[i].iova = vma->va.addr; } /* @@ -353,9 +406,23 @@ static void submit_unpin_objects(struct msm_gem_submit *submit) static void submit_attach_object_fences(struct msm_gem_submit *submit) { - int i; + struct msm_gem_vm *vm = to_msm_vm(submit->vm); + struct dma_fence *last_fence; - for (i = 0; i < submit->nr_bos; i++) { + if (msm_context_is_vmbind(submit->queue->ctx)) { + drm_gpuvm_resv_add_fence(submit->vm, &submit->exec, + submit->user_fence, + DMA_RESV_USAGE_BOOKKEEP, + DMA_RESV_USAGE_BOOKKEEP); + + last_fence = vm->last_fence; + vm->last_fence = dma_fence_unwrap_merge(submit->user_fence, last_fence); + dma_fence_put(last_fence); + + return; + } + + for (unsigned i = 0; i < submit->nr_bos; i++) { struct drm_gem_object *obj = submit->bos[i].obj; if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE) @@ -371,9 +438,8 @@ static int submit_bo(struct msm_gem_submit *submit, uint32_t idx, struct drm_gem_object **obj, uint64_t *iova) { if (idx >= submit->nr_bos) { - SUBMIT_ERROR(submit, "invalid buffer index: %u (out of %u)\n", - idx, submit->nr_bos); - return -EINVAL; + return SUBMIT_ERROR(EINVAL, submit, "invalid buffer index: %u (out of %u)\n", + idx, submit->nr_bos); } if (obj) @@ -392,10 +458,8 @@ static int submit_reloc(struct msm_gem_submit *submit, struct drm_gem_object *ob uint32_t *ptr; int ret = 0; - if (offset % 4) { - SUBMIT_ERROR(submit, "non-aligned cmdstream buffer: %u\n", offset); - return -EINVAL; - } + if (offset % 4) + return SUBMIT_ERROR(EINVAL, submit, "non-aligned cmdstream buffer: %u\n", offset); /* For now, just map the entire thing. Eventually we probably * to do it page-by-page, w/ kmap() if not vmap()d.. @@ -414,9 +478,8 @@ static int submit_reloc(struct msm_gem_submit *submit, struct drm_gem_object *ob uint64_t iova; if (submit_reloc.submit_offset % 4) { - SUBMIT_ERROR(submit, "non-aligned reloc offset: %u\n", - submit_reloc.submit_offset); - ret = -EINVAL; + ret = SUBMIT_ERROR(EINVAL, submit, "non-aligned reloc offset: %u\n", + submit_reloc.submit_offset); goto out; } @@ -425,8 +488,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct drm_gem_object *ob if ((off >= (obj->size / 4)) || (off < last_offset)) { - SUBMIT_ERROR(submit, "invalid offset %u at reloc %u\n", off, i); - ret = -EINVAL; + ret = SUBMIT_ERROR(EINVAL, submit, "invalid offset %u at reloc %u\n", off, i); goto out; } @@ -458,14 +520,15 @@ out: */ static void submit_cleanup(struct msm_gem_submit *submit, bool error) { - if (error) { + if (error) submit_unpin_objects(submit); - /* job wasn't enqueued to scheduler, so early retirement: */ - msm_submit_retire(submit); - } if (submit->exec.objects) drm_exec_fini(&submit->exec); + + /* if job wasn't enqueued to scheduler, early retirement: */ + if (error) + msm_submit_retire(submit); } void msm_submit_retire(struct msm_gem_submit *submit) @@ -474,190 +537,29 @@ void msm_submit_retire(struct msm_gem_submit *submit) for (i = 0; i < submit->nr_bos; i++) { struct drm_gem_object *obj = submit->bos[i].obj; + struct drm_gpuvm_bo *vm_bo = submit->bos[i].vm_bo; + msm_gem_lock(obj); + drm_gpuvm_bo_put(vm_bo); + msm_gem_unlock(obj); drm_gem_object_put(obj); } } -struct msm_submit_post_dep { - struct drm_syncobj *syncobj; - uint64_t point; - struct dma_fence_chain *chain; -}; - -static struct drm_syncobj **msm_parse_deps(struct msm_gem_submit *submit, - struct drm_file *file, - uint64_t in_syncobjs_addr, - uint32_t nr_in_syncobjs, - size_t syncobj_stride) -{ - struct drm_syncobj **syncobjs = NULL; - struct drm_msm_gem_submit_syncobj syncobj_desc = {0}; - int ret = 0; - uint32_t i, j; - - syncobjs = kcalloc(nr_in_syncobjs, sizeof(*syncobjs), - GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); - if (!syncobjs) - return ERR_PTR(-ENOMEM); - - for (i = 0; i < nr_in_syncobjs; ++i) { - uint64_t address = in_syncobjs_addr + i * syncobj_stride; - - if (copy_from_user(&syncobj_desc, - u64_to_user_ptr(address), - min(syncobj_stride, sizeof(syncobj_desc)))) { - ret = -EFAULT; - break; - } - - if (syncobj_desc.point && - !drm_core_check_feature(submit->dev, DRIVER_SYNCOBJ_TIMELINE)) { - ret = -EOPNOTSUPP; - break; - } - - if (syncobj_desc.flags & ~MSM_SUBMIT_SYNCOBJ_FLAGS) { - ret = -EINVAL; - break; - } - - ret = drm_sched_job_add_syncobj_dependency(&submit->base, file, - syncobj_desc.handle, syncobj_desc.point); - if (ret) - break; - - if (syncobj_desc.flags & MSM_SUBMIT_SYNCOBJ_RESET) { - syncobjs[i] = - drm_syncobj_find(file, syncobj_desc.handle); - if (!syncobjs[i]) { - ret = -EINVAL; - break; - } - } - } - - if (ret) { - for (j = 0; j <= i; ++j) { - if (syncobjs[j]) - drm_syncobj_put(syncobjs[j]); - } - kfree(syncobjs); - return ERR_PTR(ret); - } - return syncobjs; -} - -static void msm_reset_syncobjs(struct drm_syncobj **syncobjs, - uint32_t nr_syncobjs) -{ - uint32_t i; - - for (i = 0; syncobjs && i < nr_syncobjs; ++i) { - if (syncobjs[i]) - drm_syncobj_replace_fence(syncobjs[i], NULL); - } -} - -static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev, - struct drm_file *file, - uint64_t syncobjs_addr, - uint32_t nr_syncobjs, - size_t syncobj_stride) -{ - struct msm_submit_post_dep *post_deps; - struct drm_msm_gem_submit_syncobj syncobj_desc = {0}; - int ret = 0; - uint32_t i, j; - - post_deps = kcalloc(nr_syncobjs, sizeof(*post_deps), - GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); - if (!post_deps) - return ERR_PTR(-ENOMEM); - - for (i = 0; i < nr_syncobjs; ++i) { - uint64_t address = syncobjs_addr + i * syncobj_stride; - - if (copy_from_user(&syncobj_desc, - u64_to_user_ptr(address), - min(syncobj_stride, sizeof(syncobj_desc)))) { - ret = -EFAULT; - break; - } - - post_deps[i].point = syncobj_desc.point; - - if (syncobj_desc.flags) { - ret = -EINVAL; - break; - } - - if (syncobj_desc.point) { - if (!drm_core_check_feature(dev, - DRIVER_SYNCOBJ_TIMELINE)) { - ret = -EOPNOTSUPP; - break; - } - - post_deps[i].chain = dma_fence_chain_alloc(); - if (!post_deps[i].chain) { - ret = -ENOMEM; - break; - } - } - - post_deps[i].syncobj = - drm_syncobj_find(file, syncobj_desc.handle); - if (!post_deps[i].syncobj) { - ret = -EINVAL; - break; - } - } - - if (ret) { - for (j = 0; j <= i; ++j) { - dma_fence_chain_free(post_deps[j].chain); - if (post_deps[j].syncobj) - drm_syncobj_put(post_deps[j].syncobj); - } - - kfree(post_deps); - return ERR_PTR(ret); - } - - return post_deps; -} - -static void msm_process_post_deps(struct msm_submit_post_dep *post_deps, - uint32_t count, struct dma_fence *fence) -{ - uint32_t i; - - for (i = 0; post_deps && i < count; ++i) { - if (post_deps[i].chain) { - drm_syncobj_add_point(post_deps[i].syncobj, - post_deps[i].chain, - fence, post_deps[i].point); - post_deps[i].chain = NULL; - } else { - drm_syncobj_replace_fence(post_deps[i].syncobj, - fence); - } - } -} - int msm_ioctl_gem_submit(struct drm_device *dev, void *data, struct drm_file *file) { struct msm_drm_private *priv = dev->dev_private; struct drm_msm_gem_submit *args = data; - struct msm_file_private *ctx = file->driver_priv; + struct msm_context *ctx = file->driver_priv; struct msm_gem_submit *submit = NULL; struct msm_gpu *gpu = priv->gpu; struct msm_gpu_submitqueue *queue; struct msm_ringbuffer *ring; - struct msm_submit_post_dep *post_deps = NULL; + struct msm_syncobj_post_dep *post_deps = NULL; struct drm_syncobj **syncobjs_to_reset = NULL; + struct sync_file *sync_file = NULL; + unsigned cmds_to_parse; int out_fence_fd = -1; unsigned i; int ret; @@ -668,19 +570,17 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, if (args->pad) return -EINVAL; - if (unlikely(!ctx->aspace) && !capable(CAP_SYS_RAWIO)) { - DRM_ERROR_RATELIMITED("IOMMU support or CAP_SYS_RAWIO required!\n"); - return -EPERM; - } + if (to_msm_vm(ctx->vm)->unusable) + return UERR(EPIPE, dev, "context is unusable"); /* for now, we just have 3d pipe.. eventually this would need to * be more clever to dispatch to appropriate gpu module: */ if (MSM_PIPE_ID(args->flags) != MSM_PIPE_3D0) - return -EINVAL; + return UERR(EINVAL, dev, "invalid pipe"); if (MSM_PIPE_FLAGS(args->flags) & ~MSM_SUBMIT_FLAGS) - return -EINVAL; + return UERR(EINVAL, dev, "invalid flags"); if (args->flags & MSM_SUBMIT_SUDO) { if (!IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) || @@ -692,6 +592,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, if (!queue) return -ENOENT; + if (queue->flags & MSM_SUBMITQUEUE_VM_BIND) { + ret = UERR(EINVAL, dev, "Invalid queue type"); + goto out_post_unlock; + } + ring = gpu->rb[queue->ring_nr]; if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) { @@ -702,7 +607,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, } } - submit = submit_create(dev, gpu, queue, args->nr_bos, args->nr_cmds); + submit = submit_create(dev, gpu, queue, args->nr_bos, args->nr_cmds, + file->client_id); if (IS_ERR(submit)) { ret = PTR_ERR(submit); goto out_post_unlock; @@ -724,7 +630,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, in_fence = sync_file_get_fence(args->fence_fd); if (!in_fence) { - ret = -EINVAL; + ret = UERR(EINVAL, dev, "invalid in-fence"); goto out_unlock; } @@ -734,10 +640,10 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, } if (args->flags & MSM_SUBMIT_SYNCOBJ_IN) { - syncobjs_to_reset = msm_parse_deps(submit, file, - args->in_syncobjs, - args->nr_in_syncobjs, - args->syncobj_stride); + syncobjs_to_reset = msm_syncobj_parse_deps(dev, &submit->base, + file, args->in_syncobjs, + args->nr_in_syncobjs, + args->syncobj_stride); if (IS_ERR(syncobjs_to_reset)) { ret = PTR_ERR(syncobjs_to_reset); goto out_unlock; @@ -745,10 +651,10 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, } if (args->flags & MSM_SUBMIT_SYNCOBJ_OUT) { - post_deps = msm_parse_post_deps(dev, file, - args->out_syncobjs, - args->nr_out_syncobjs, - args->syncobj_stride); + post_deps = msm_syncobj_parse_post_deps(dev, file, + args->out_syncobjs, + args->nr_out_syncobjs, + args->syncobj_stride); if (IS_ERR(post_deps)) { ret = PTR_ERR(post_deps); goto out_unlock; @@ -778,7 +684,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, if (ret) goto out; - for (i = 0; i < args->nr_cmds; i++) { + cmds_to_parse = msm_context_is_vmbind(ctx) ? 0 : args->nr_cmds; + + for (i = 0; i < cmds_to_parse; i++) { struct drm_gem_object *obj; uint64_t iova; @@ -787,10 +695,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, goto out; if (!submit->cmd[i].size || - ((submit->cmd[i].size + submit->cmd[i].offset) > - obj->size / 4)) { - SUBMIT_ERROR(submit, "invalid cmdstream size: %u\n", submit->cmd[i].size * 4); - ret = -EINVAL; + (size_add(submit->cmd[i].size, submit->cmd[i].offset) > obj->size / 4)) { + ret = UERR(EINVAL, dev, "invalid cmdstream size: %u\n", + submit->cmd[i].size * 4); goto out; } @@ -800,8 +707,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, continue; if (!gpu->allow_relocs) { - SUBMIT_ERROR(submit, "relocs not allowed\n"); - ret = -EINVAL; + ret = UERR(EINVAL, dev, "relocs not allowed\n"); goto out; } @@ -811,7 +717,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, goto out; } - submit->nr_cmds = i; + submit->nr_cmds = args->nr_cmds; idr_preload(GFP_KERNEL); @@ -827,7 +733,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, (!args->fence || idr_find(&queue->fence_idr, args->fence))) { spin_unlock(&queue->idr_lock); idr_preload_end(); - ret = -EINVAL; + ret = UERR(EINVAL, dev, "invalid in-fence-sn"); goto out; } @@ -869,13 +775,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, } if (ret == 0 && args->flags & MSM_SUBMIT_FENCE_FD_OUT) { - struct sync_file *sync_file = sync_file_create(submit->user_fence); - if (!sync_file) { + sync_file = sync_file_create(submit->user_fence); + if (!sync_file) ret = -ENOMEM; - } else { - fd_install(out_fence_fd, sync_file->file); - args->fence_fd = out_fence_fd; - } } if (ret) @@ -883,6 +785,18 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, submit_attach_object_fences(submit); + if (msm_context_is_vmbind(ctx)) { + /* + * If we are not using VM_BIND, submit_pin_vmas() will validate + * just the BOs attached to the submit. In that case we don't + * need to validate the _entire_ vm, because userspace tracked + * what BOs are associated with the submit. + */ + ret = drm_gpuvm_validate(submit->vm, &submit->exec); + if (ret) + goto out; + } + /* The scheduler owns a ref now: */ msm_gem_submit_get(submit); @@ -893,18 +807,23 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, args->fence = submit->fence_id; queue->last_fence = submit->fence_id; - msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs); - msm_process_post_deps(post_deps, args->nr_out_syncobjs, - submit->user_fence); - + msm_syncobj_reset(syncobjs_to_reset, args->nr_in_syncobjs); + msm_syncobj_process_post_deps(post_deps, args->nr_out_syncobjs, submit->user_fence); out: submit_cleanup(submit, !!ret); out_unlock: mutex_unlock(&queue->lock); out_post_unlock: - if (ret && (out_fence_fd >= 0)) - put_unused_fd(out_fence_fd); + if (ret) { + if (out_fence_fd >= 0) + put_unused_fd(out_fence_fd); + if (sync_file) + fput(sync_file->file); + } else if (sync_file) { + fd_install(out_fence_fd, sync_file->file); + args->fence_fd = out_fence_fd; + } if (!IS_ERR_OR_NULL(submit)) { msm_gem_submit_put(submit); diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 11e842dda73c..71d5238437eb 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -4,174 +4,1619 @@ * Author: Rob Clark <robdclark@gmail.com> */ +#include "drm/drm_file.h" +#include "drm/msm_drm.h" +#include "linux/file.h" +#include "linux/sync_file.h" + #include "msm_drv.h" -#include "msm_fence.h" #include "msm_gem.h" +#include "msm_gpu.h" #include "msm_mmu.h" +#include "msm_syncobj.h" + +#define vm_dbg(fmt, ...) pr_debug("%s:%d: "fmt"\n", __func__, __LINE__, ##__VA_ARGS__) + +static uint vm_log_shift = 0; +MODULE_PARM_DESC(vm_log_shift, "Length of VM op log"); +module_param_named(vm_log_shift, vm_log_shift, uint, 0600); + +/** + * struct msm_vm_map_op - create new pgtable mapping + */ +struct msm_vm_map_op { + /** @iova: start address for mapping */ + uint64_t iova; + /** @range: size of the region to map */ + uint64_t range; + /** @offset: offset into @sgt to map */ + uint64_t offset; + /** @sgt: pages to map, or NULL for a PRR mapping */ + struct sg_table *sgt; + /** @prot: the mapping protection flags */ + int prot; + + /** + * @queue_id: The id of the submitqueue the operation is performed + * on, or zero for (in particular) UNMAP ops triggered outside of + * a submitqueue (ie. process cleanup) + */ + int queue_id; +}; + +/** + * struct msm_vm_unmap_op - unmap a range of pages from pgtable + */ +struct msm_vm_unmap_op { + /** @iova: start address for unmap */ + uint64_t iova; + /** @range: size of region to unmap */ + uint64_t range; + + /** @reason: The reason for the unmap */ + const char *reason; + + /** + * @queue_id: The id of the submitqueue the operation is performed + * on, or zero for (in particular) UNMAP ops triggered outside of + * a submitqueue (ie. process cleanup) + */ + int queue_id; +}; + +/** + * struct msm_vma_op - A MAP or UNMAP operation + */ +struct msm_vm_op { + /** @op: The operation type */ + enum { + MSM_VM_OP_MAP = 1, + MSM_VM_OP_UNMAP, + } op; + union { + /** @map: Parameters used if op == MSM_VMA_OP_MAP */ + struct msm_vm_map_op map; + /** @unmap: Parameters used if op == MSM_VMA_OP_UNMAP */ + struct msm_vm_unmap_op unmap; + }; + /** @node: list head in msm_vm_bind_job::vm_ops */ + struct list_head node; + + /** + * @obj: backing object for pages to be mapped/unmapped + * + * Async unmap ops, in particular, must hold a reference to the + * original GEM object backing the mapping that will be unmapped. + * But the same can be required in the map path, for example if + * there is not a corresponding unmap op, such as process exit. + * + * This ensures that the pages backing the mapping are not freed + * before the mapping is torn down. + */ + struct drm_gem_object *obj; +}; + +/** + * struct msm_vm_bind_job - Tracking for a VM_BIND ioctl + * + * A table of userspace requested VM updates (MSM_VM_BIND_OP_UNMAP/MAP/MAP_NULL) + * gets applied to the vm, generating a list of VM ops (MSM_VM_OP_MAP/UNMAP) + * which are applied to the pgtables asynchronously. For example a userspace + * requested MSM_VM_BIND_OP_MAP could end up generating both an MSM_VM_OP_UNMAP + * to unmap an existing mapping, and a MSM_VM_OP_MAP to apply the new mapping. + */ +struct msm_vm_bind_job { + /** @base: base class for drm_sched jobs */ + struct drm_sched_job base; + /** @vm: The VM being operated on */ + struct drm_gpuvm *vm; + /** @fence: The fence that is signaled when job completes */ + struct dma_fence *fence; + /** @queue: The queue that the job runs on */ + struct msm_gpu_submitqueue *queue; + /** @prealloc: Tracking for pre-allocated MMU pgtable pages */ + struct msm_mmu_prealloc prealloc; + /** @vm_ops: a list of struct msm_vm_op */ + struct list_head vm_ops; + /** @bos_pinned: are the GEM objects being bound pinned? */ + bool bos_pinned; + /** @nr_ops: the number of userspace requested ops */ + unsigned int nr_ops; + /** + * @ops: the userspace requested ops + * + * The userspace requested ops are copied/parsed and validated + * before we start applying the updates to try to do as much up- + * front error checking as possible, to avoid the VM being in an + * undefined state due to partially executed VM_BIND. + * + * This table also serves to hold a reference to the backing GEM + * objects. + */ + struct msm_vm_bind_op { + uint32_t op; + uint32_t flags; + union { + struct drm_gem_object *obj; + uint32_t handle; + }; + uint64_t obj_offset; + uint64_t iova; + uint64_t range; + } ops[]; +}; + +#define job_foreach_bo(obj, _job) \ + for (unsigned i = 0; i < (_job)->nr_ops; i++) \ + if ((obj = (_job)->ops[i].obj)) + +static inline struct msm_vm_bind_job *to_msm_vm_bind_job(struct drm_sched_job *job) +{ + return container_of(job, struct msm_vm_bind_job, base); +} static void -msm_gem_address_space_destroy(struct kref *kref) +msm_gem_vm_free(struct drm_gpuvm *gpuvm) +{ + struct msm_gem_vm *vm = container_of(gpuvm, struct msm_gem_vm, base); + + drm_mm_takedown(&vm->mm); + if (vm->mmu) + vm->mmu->funcs->destroy(vm->mmu); + dma_fence_put(vm->last_fence); + put_pid(vm->pid); + kfree(vm->log); + kfree(vm); +} + +/** + * msm_gem_vm_unusable() - Mark a VM as unusable + * @gpuvm: the VM to mark unusable + */ +void +msm_gem_vm_unusable(struct drm_gpuvm *gpuvm) { - struct msm_gem_address_space *aspace = container_of(kref, - struct msm_gem_address_space, kref); + struct msm_gem_vm *vm = to_msm_vm(gpuvm); + uint32_t vm_log_len = (1 << vm->log_shift); + uint32_t vm_log_mask = vm_log_len - 1; + uint32_t nr_vm_logs; + int first; + + vm->unusable = true; - drm_mm_takedown(&aspace->mm); - if (aspace->mmu) - aspace->mmu->funcs->destroy(aspace->mmu); - put_pid(aspace->pid); - kfree(aspace); + /* Bail if no log, or empty log: */ + if (!vm->log || !vm->log[0].op) + return; + + mutex_lock(&vm->mmu_lock); + + /* + * log_idx is the next entry to overwrite, meaning it is the oldest, or + * first, entry (other than the special case handled below where the + * log hasn't wrapped around yet) + */ + first = vm->log_idx; + + if (!vm->log[first].op) { + /* + * If the next log entry has not been written yet, then only + * entries 0 to idx-1 are valid (ie. we haven't wrapped around + * yet) + */ + nr_vm_logs = MAX(0, first - 1); + first = 0; + } else { + nr_vm_logs = vm_log_len; + } + + pr_err("vm-log:\n"); + for (int i = 0; i < nr_vm_logs; i++) { + int idx = (i + first) & vm_log_mask; + struct msm_gem_vm_log_entry *e = &vm->log[idx]; + pr_err(" - %s:%d: 0x%016llx-0x%016llx\n", + e->op, e->queue_id, e->iova, + e->iova + e->range); + } + + mutex_unlock(&vm->mmu_lock); } +static void +vm_log(struct msm_gem_vm *vm, const char *op, uint64_t iova, uint64_t range, int queue_id) +{ + int idx; + + if (!vm->managed) + lockdep_assert_held(&vm->mmu_lock); + + vm_dbg("%s:%p:%d: %016llx %016llx", op, vm, queue_id, iova, iova + range); + + if (!vm->log) + return; + + idx = vm->log_idx; + vm->log[idx].op = op; + vm->log[idx].iova = iova; + vm->log[idx].range = range; + vm->log[idx].queue_id = queue_id; + vm->log_idx = (vm->log_idx + 1) & ((1 << vm->log_shift) - 1); +} -void msm_gem_address_space_put(struct msm_gem_address_space *aspace) +static void +vm_unmap_op(struct msm_gem_vm *vm, const struct msm_vm_unmap_op *op) { - if (aspace) - kref_put(&aspace->kref, msm_gem_address_space_destroy); + const char *reason = op->reason; + + if (!reason) + reason = "unmap"; + + vm_log(vm, reason, op->iova, op->range, op->queue_id); + + vm->mmu->funcs->unmap(vm->mmu, op->iova, op->range); } -struct msm_gem_address_space * -msm_gem_address_space_get(struct msm_gem_address_space *aspace) +static int +vm_map_op(struct msm_gem_vm *vm, const struct msm_vm_map_op *op) { - if (!IS_ERR_OR_NULL(aspace)) - kref_get(&aspace->kref); + vm_log(vm, "map", op->iova, op->range, op->queue_id); - return aspace; + return vm->mmu->funcs->map(vm->mmu, op->iova, op->sgt, op->offset, + op->range, op->prot); } /* Actually unmap memory for the vma */ -void msm_gem_vma_purge(struct msm_gem_vma *vma) +void msm_gem_vma_unmap(struct drm_gpuva *vma, const char *reason) { - struct msm_gem_address_space *aspace = vma->aspace; - unsigned size = vma->node.size; + struct msm_gem_vm *vm = to_msm_vm(vma->vm); + struct msm_gem_vma *msm_vma = to_msm_vma(vma); /* Don't do anything if the memory isn't mapped */ - if (!vma->mapped) + if (!msm_vma->mapped) return; - aspace->mmu->funcs->unmap(aspace->mmu, vma->iova, size); + /* + * The mmu_lock is only needed when preallocation is used. But + * in that case we don't need to worry about recursion into + * shrinker + */ + if (!vm->managed) + mutex_lock(&vm->mmu_lock); - vma->mapped = false; + vm_unmap_op(vm, &(struct msm_vm_unmap_op){ + .iova = vma->va.addr, + .range = vma->va.range, + .reason = reason, + }); + + if (!vm->managed) + mutex_unlock(&vm->mmu_lock); + + msm_vma->mapped = false; } /* Map and pin vma: */ int -msm_gem_vma_map(struct msm_gem_vma *vma, int prot, - struct sg_table *sgt, int size) +msm_gem_vma_map(struct drm_gpuva *vma, int prot, struct sg_table *sgt) { - struct msm_gem_address_space *aspace = vma->aspace; + struct msm_gem_vm *vm = to_msm_vm(vma->vm); + struct msm_gem_vma *msm_vma = to_msm_vma(vma); int ret; - if (GEM_WARN_ON(!vma->iova)) + if (GEM_WARN_ON(!vma->va.addr)) return -EINVAL; - if (vma->mapped) + if (msm_vma->mapped) return 0; - vma->mapped = true; + msm_vma->mapped = true; - if (!aspace) - return 0; + /* + * The mmu_lock is only needed when preallocation is used. But + * in that case we don't need to worry about recursion into + * shrinker + */ + if (!vm->managed) + mutex_lock(&vm->mmu_lock); /* - * NOTE: iommu/io-pgtable can allocate pages, so we cannot hold + * NOTE: if not using pgtable preallocation, we cannot hold * a lock across map/unmap which is also used in the job_run() * path, as this can cause deadlock in job_run() vs shrinker/ * reclaim. - * - * Revisit this if we can come up with a scheme to pre-alloc pages - * for the pgtable in map/unmap ops. */ - ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt, size, prot); + ret = vm_map_op(vm, &(struct msm_vm_map_op){ + .iova = vma->va.addr, + .range = vma->va.range, + .offset = vma->gem.offset, + .sgt = sgt, + .prot = prot, + }); - if (ret) { - vma->mapped = false; - } + if (!vm->managed) + mutex_unlock(&vm->mmu_lock); + + if (ret) + msm_vma->mapped = false; return ret; } /* Close an iova. Warn if it is still in use */ -void msm_gem_vma_close(struct msm_gem_vma *vma) +void msm_gem_vma_close(struct drm_gpuva *vma) { - struct msm_gem_address_space *aspace = vma->aspace; + struct msm_gem_vm *vm = to_msm_vm(vma->vm); + struct msm_gem_vma *msm_vma = to_msm_vma(vma); - GEM_WARN_ON(vma->mapped); + GEM_WARN_ON(msm_vma->mapped); - spin_lock(&aspace->lock); - if (vma->iova) - drm_mm_remove_node(&vma->node); - spin_unlock(&aspace->lock); + drm_gpuvm_resv_assert_held(&vm->base); + + if (vma->gem.obj) + msm_gem_assert_locked(vma->gem.obj); - vma->iova = 0; + if (vma->va.addr && vm->managed) + drm_mm_remove_node(&msm_vma->node); - msm_gem_address_space_put(aspace); + drm_gpuva_remove(vma); + drm_gpuva_unlink(vma); + + kfree(vma); } -struct msm_gem_vma *msm_gem_vma_new(struct msm_gem_address_space *aspace) +/* Create a new vma and allocate an iova for it */ +struct drm_gpuva * +msm_gem_vma_new(struct drm_gpuvm *gpuvm, struct drm_gem_object *obj, + u64 offset, u64 range_start, u64 range_end) { + struct msm_gem_vm *vm = to_msm_vm(gpuvm); + struct drm_gpuvm_bo *vm_bo; struct msm_gem_vma *vma; + int ret; + + drm_gpuvm_resv_assert_held(&vm->base); vma = kzalloc(sizeof(*vma), GFP_KERNEL); if (!vma) - return NULL; + return ERR_PTR(-ENOMEM); + + if (vm->managed) { + BUG_ON(offset != 0); + BUG_ON(!obj); /* NULL mappings not valid for kernel managed VM */ + ret = drm_mm_insert_node_in_range(&vm->mm, &vma->node, + obj->size, PAGE_SIZE, 0, + range_start, range_end, 0); + + if (ret) + goto err_free_vma; + + range_start = vma->node.start; + range_end = range_start + obj->size; + } + + if (obj) + GEM_WARN_ON((range_end - range_start) > obj->size); + + struct drm_gpuva_op_map op_map = { + .va.addr = range_start, + .va.range = range_end - range_start, + .gem.obj = obj, + .gem.offset = offset, + }; + + drm_gpuva_init_from_op(&vma->base, &op_map); + vma->mapped = false; + + ret = drm_gpuva_insert(&vm->base, &vma->base); + if (ret) + goto err_free_range; + + if (!obj) + return &vma->base; + + vm_bo = drm_gpuvm_bo_obtain(&vm->base, obj); + if (IS_ERR(vm_bo)) { + ret = PTR_ERR(vm_bo); + goto err_va_remove; + } - vma->aspace = aspace; + drm_gpuvm_bo_extobj_add(vm_bo); + drm_gpuva_link(&vma->base, vm_bo); + GEM_WARN_ON(drm_gpuvm_bo_put(vm_bo)); - return vma; + return &vma->base; + +err_va_remove: + drm_gpuva_remove(&vma->base); +err_free_range: + if (vm->managed) + drm_mm_remove_node(&vma->node); +err_free_vma: + kfree(vma); + return ERR_PTR(ret); } -/* Initialize a new vma and allocate an iova for it */ -int msm_gem_vma_init(struct msm_gem_vma *vma, int size, - u64 range_start, u64 range_end) +static int +msm_gem_vm_bo_validate(struct drm_gpuvm_bo *vm_bo, struct drm_exec *exec) { - struct msm_gem_address_space *aspace = vma->aspace; + struct drm_gem_object *obj = vm_bo->obj; + struct drm_gpuva *vma; int ret; - if (GEM_WARN_ON(!aspace)) - return -EINVAL; + vm_dbg("validate: %p", obj); + + msm_gem_assert_locked(obj); - if (GEM_WARN_ON(vma->iova)) - return -EBUSY; + drm_gpuvm_bo_for_each_va (vma, vm_bo) { + ret = msm_gem_pin_vma_locked(obj, vma); + if (ret) + return ret; + } + + return 0; +} - spin_lock(&aspace->lock); - ret = drm_mm_insert_node_in_range(&aspace->mm, &vma->node, - size, PAGE_SIZE, 0, - range_start, range_end, 0); - spin_unlock(&aspace->lock); +struct op_arg { + unsigned flags; + struct msm_vm_bind_job *job; + const struct msm_vm_bind_op *op; + bool kept; +}; + +static int +vm_op_enqueue(struct op_arg *arg, struct msm_vm_op _op) +{ + struct msm_vm_op *op = kmalloc(sizeof(*op), GFP_KERNEL); + if (!op) + return -ENOMEM; + + *op = _op; + list_add_tail(&op->node, &arg->job->vm_ops); + + if (op->obj) + drm_gem_object_get(op->obj); + + return 0; +} + +static struct drm_gpuva * +vma_from_op(struct op_arg *arg, struct drm_gpuva_op_map *op) +{ + return msm_gem_vma_new(arg->job->vm, op->gem.obj, op->gem.offset, + op->va.addr, op->va.addr + op->va.range); +} + +static int +msm_gem_vm_sm_step_map(struct drm_gpuva_op *op, void *_arg) +{ + struct op_arg *arg = _arg; + struct msm_vm_bind_job *job = arg->job; + struct drm_gem_object *obj = op->map.gem.obj; + struct drm_gpuva *vma; + struct sg_table *sgt; + unsigned prot; + int ret; + + if (arg->kept) + return 0; + + vma = vma_from_op(arg, &op->map); + if (WARN_ON(IS_ERR(vma))) + return PTR_ERR(vma); + + vm_dbg("%p:%p:%p: %016llx %016llx", vma->vm, vma, vma->gem.obj, + vma->va.addr, vma->va.range); + + if (obj) { + sgt = to_msm_bo(obj)->sgt; + prot = msm_gem_prot(obj); + } else { + sgt = NULL; + prot = IOMMU_READ | IOMMU_WRITE; + } + + ret = vm_op_enqueue(arg, (struct msm_vm_op){ + .op = MSM_VM_OP_MAP, + .map = { + .sgt = sgt, + .iova = vma->va.addr, + .range = vma->va.range, + .offset = vma->gem.offset, + .prot = prot, + .queue_id = job->queue->id, + }, + .obj = vma->gem.obj, + }); if (ret) return ret; - vma->iova = vma->node.start; - vma->mapped = false; + vma->flags = ((struct op_arg *)arg)->flags; + to_msm_vma(vma)->mapped = true; - kref_get(&aspace->kref); + return 0; +} + +static int +msm_gem_vm_sm_step_remap(struct drm_gpuva_op *op, void *arg) +{ + struct msm_vm_bind_job *job = ((struct op_arg *)arg)->job; + struct drm_gpuvm *vm = job->vm; + struct drm_gpuva *orig_vma = op->remap.unmap->va; + struct drm_gpuva *prev_vma = NULL, *next_vma = NULL; + struct drm_gpuvm_bo *vm_bo = orig_vma->vm_bo; + bool mapped = to_msm_vma(orig_vma)->mapped; + unsigned flags; + int ret; + + vm_dbg("orig_vma: %p:%p:%p: %016llx %016llx", vm, orig_vma, + orig_vma->gem.obj, orig_vma->va.addr, orig_vma->va.range); + + if (mapped) { + uint64_t unmap_start, unmap_range; + + drm_gpuva_op_remap_to_unmap_range(&op->remap, &unmap_start, &unmap_range); + + ret = vm_op_enqueue(arg, (struct msm_vm_op){ + .op = MSM_VM_OP_UNMAP, + .unmap = { + .iova = unmap_start, + .range = unmap_range, + .queue_id = job->queue->id, + }, + .obj = orig_vma->gem.obj, + }); + + if (ret) + return ret; + + /* + * Part of this GEM obj is still mapped, but we're going to kill the + * existing VMA and replace it with one or two new ones (ie. two if + * the unmapped range is in the middle of the existing (unmap) VMA). + * So just set the state to unmapped: + */ + to_msm_vma(orig_vma)->mapped = false; + } + + /* + * Hold a ref to the vm_bo between the msm_gem_vma_close() and the + * creation of the new prev/next vma's, in case the vm_bo is tracked + * in the VM's evict list: + */ + if (vm_bo) + drm_gpuvm_bo_get(vm_bo); + + /* + * The prev_vma and/or next_vma are replacing the unmapped vma, and + * therefore should preserve it's flags: + */ + flags = orig_vma->flags; + + msm_gem_vma_close(orig_vma); + + if (op->remap.prev) { + prev_vma = vma_from_op(arg, op->remap.prev); + if (WARN_ON(IS_ERR(prev_vma))) + return PTR_ERR(prev_vma); + + vm_dbg("prev_vma: %p:%p: %016llx %016llx", vm, prev_vma, prev_vma->va.addr, prev_vma->va.range); + to_msm_vma(prev_vma)->mapped = mapped; + prev_vma->flags = flags; + } + + if (op->remap.next) { + next_vma = vma_from_op(arg, op->remap.next); + if (WARN_ON(IS_ERR(next_vma))) + return PTR_ERR(next_vma); + + vm_dbg("next_vma: %p:%p: %016llx %016llx", vm, next_vma, next_vma->va.addr, next_vma->va.range); + to_msm_vma(next_vma)->mapped = mapped; + next_vma->flags = flags; + } + + if (!mapped) + drm_gpuvm_bo_evict(vm_bo, true); + + /* Drop the previous ref: */ + drm_gpuvm_bo_put(vm_bo); + + return 0; +} + +static int +msm_gem_vm_sm_step_unmap(struct drm_gpuva_op *op, void *_arg) +{ + struct op_arg *arg = _arg; + struct msm_vm_bind_job *job = arg->job; + struct drm_gpuva *vma = op->unmap.va; + struct msm_gem_vma *msm_vma = to_msm_vma(vma); + int ret; + + vm_dbg("%p:%p:%p: %016llx %016llx", vma->vm, vma, vma->gem.obj, + vma->va.addr, vma->va.range); + + /* + * Detect in-place remap. Turnip does this to change the vma flags, + * in particular MSM_VMA_DUMP. In this case we want to avoid actually + * touching the page tables, as that would require synchronization + * against SUBMIT jobs running on the GPU. + */ + if (op->unmap.keep && + (arg->op->op == MSM_VM_BIND_OP_MAP) && + (vma->gem.obj == arg->op->obj) && + (vma->gem.offset == arg->op->obj_offset) && + (vma->va.addr == arg->op->iova) && + (vma->va.range == arg->op->range)) { + /* We are only expecting a single in-place unmap+map cb pair: */ + WARN_ON(arg->kept); + + /* Leave the existing VMA in place, but signal that to the map cb: */ + arg->kept = true; + + /* Only flags are changing, so update that in-place: */ + unsigned orig_flags = vma->flags & (DRM_GPUVA_USERBITS - 1); + vma->flags = orig_flags | arg->flags; + + return 0; + } + + if (!msm_vma->mapped) + goto out_close; + + ret = vm_op_enqueue(arg, (struct msm_vm_op){ + .op = MSM_VM_OP_UNMAP, + .unmap = { + .iova = vma->va.addr, + .range = vma->va.range, + .queue_id = job->queue->id, + }, + .obj = vma->gem.obj, + }); + + if (ret) + return ret; + + msm_vma->mapped = false; + +out_close: + msm_gem_vma_close(vma); return 0; } -struct msm_gem_address_space * -msm_gem_address_space_create(struct msm_mmu *mmu, const char *name, - u64 va_start, u64 size) +static const struct drm_gpuvm_ops msm_gpuvm_ops = { + .vm_free = msm_gem_vm_free, + .vm_bo_validate = msm_gem_vm_bo_validate, + .sm_step_map = msm_gem_vm_sm_step_map, + .sm_step_remap = msm_gem_vm_sm_step_remap, + .sm_step_unmap = msm_gem_vm_sm_step_unmap, +}; + +static struct dma_fence * +msm_vma_job_run(struct drm_sched_job *_job) +{ + struct msm_vm_bind_job *job = to_msm_vm_bind_job(_job); + struct msm_gem_vm *vm = to_msm_vm(job->vm); + struct drm_gem_object *obj; + int ret = vm->unusable ? -EINVAL : 0; + + vm_dbg(""); + + mutex_lock(&vm->mmu_lock); + vm->mmu->prealloc = &job->prealloc; + + while (!list_empty(&job->vm_ops)) { + struct msm_vm_op *op = + list_first_entry(&job->vm_ops, struct msm_vm_op, node); + + switch (op->op) { + case MSM_VM_OP_MAP: + /* + * On error, stop trying to map new things.. but we + * still want to process the unmaps (or in particular, + * the drm_gem_object_put()s) + */ + if (!ret) + ret = vm_map_op(vm, &op->map); + break; + case MSM_VM_OP_UNMAP: + vm_unmap_op(vm, &op->unmap); + break; + } + drm_gem_object_put(op->obj); + list_del(&op->node); + kfree(op); + } + + vm->mmu->prealloc = NULL; + mutex_unlock(&vm->mmu_lock); + + /* + * We failed to perform at least _some_ of the pgtable updates, so + * now the VM is in an undefined state. Game over! + */ + if (ret) + msm_gem_vm_unusable(job->vm); + + job_foreach_bo (obj, job) { + msm_gem_lock(obj); + msm_gem_unpin_locked(obj); + msm_gem_unlock(obj); + } + + /* VM_BIND ops are synchronous, so no fence to wait on: */ + return NULL; +} + +static void +msm_vma_job_free(struct drm_sched_job *_job) { - struct msm_gem_address_space *aspace; + struct msm_vm_bind_job *job = to_msm_vm_bind_job(_job); + struct msm_gem_vm *vm = to_msm_vm(job->vm); + struct drm_gem_object *obj; + + vm->mmu->funcs->prealloc_cleanup(vm->mmu, &job->prealloc); + + atomic_sub(job->prealloc.count, &vm->prealloc_throttle.in_flight); + + drm_sched_job_cleanup(_job); + + job_foreach_bo (obj, job) + drm_gem_object_put(obj); + + msm_submitqueue_put(job->queue); + dma_fence_put(job->fence); + + /* In error paths, we could have unexecuted ops: */ + while (!list_empty(&job->vm_ops)) { + struct msm_vm_op *op = + list_first_entry(&job->vm_ops, struct msm_vm_op, node); + list_del(&op->node); + kfree(op); + } + + wake_up(&vm->prealloc_throttle.wait); + + kfree(job); +} + +static const struct drm_sched_backend_ops msm_vm_bind_ops = { + .run_job = msm_vma_job_run, + .free_job = msm_vma_job_free +}; + +/** + * msm_gem_vm_create() - Create and initialize a &msm_gem_vm + * @drm: the drm device + * @mmu: the backing MMU objects handling mapping/unmapping + * @name: the name of the VM + * @va_start: the start offset of the VA space + * @va_size: the size of the VA space + * @managed: is it a kernel managed VM? + * + * In a kernel managed VM, the kernel handles address allocation, and only + * synchronous operations are supported. In a user managed VM, userspace + * handles virtual address allocation, and both async and sync operations + * are supported. + */ +struct drm_gpuvm * +msm_gem_vm_create(struct drm_device *drm, struct msm_mmu *mmu, const char *name, + u64 va_start, u64 va_size, bool managed) +{ + /* + * We mostly want to use DRM_GPUVM_RESV_PROTECTED, except that + * makes drm_gpuvm_bo_evict() a no-op for extobjs (ie. we loose + * tracking that an extobj is evicted) :facepalm: + */ + enum drm_gpuvm_flags flags = 0; + struct msm_gem_vm *vm; + struct drm_gem_object *dummy_gem; + int ret = 0; if (IS_ERR(mmu)) return ERR_CAST(mmu); - aspace = kzalloc(sizeof(*aspace), GFP_KERNEL); - if (!aspace) + vm = kzalloc(sizeof(*vm), GFP_KERNEL); + if (!vm) + return ERR_PTR(-ENOMEM); + + dummy_gem = drm_gpuvm_resv_object_alloc(drm); + if (!dummy_gem) { + ret = -ENOMEM; + goto err_free_vm; + } + + if (!managed) { + struct drm_sched_init_args args = { + .ops = &msm_vm_bind_ops, + .num_rqs = 1, + .credit_limit = 1, + .timeout = MAX_SCHEDULE_TIMEOUT, + .name = "msm-vm-bind", + .dev = drm->dev, + }; + + ret = drm_sched_init(&vm->sched, &args); + if (ret) + goto err_free_dummy; + + init_waitqueue_head(&vm->prealloc_throttle.wait); + } + + drm_gpuvm_init(&vm->base, name, flags, drm, dummy_gem, + va_start, va_size, 0, 0, &msm_gpuvm_ops); + drm_gem_object_put(dummy_gem); + + vm->mmu = mmu; + mutex_init(&vm->mmu_lock); + vm->managed = managed; + + drm_mm_init(&vm->mm, va_start, va_size); + + /* + * We don't really need vm log for kernel managed VMs, as the kernel + * is responsible for ensuring that GEM objs are mapped if they are + * used by a submit. Furthermore we piggyback on mmu_lock to serialize + * access to the log. + * + * Limit the max log_shift to 8 to prevent userspace from asking us + * for an unreasonable log size. + */ + if (!managed) + vm->log_shift = MIN(vm_log_shift, 8); + + if (vm->log_shift) { + vm->log = kmalloc_array(1 << vm->log_shift, sizeof(vm->log[0]), + GFP_KERNEL | __GFP_ZERO); + } + + return &vm->base; + +err_free_dummy: + drm_gem_object_put(dummy_gem); + +err_free_vm: + kfree(vm); + return ERR_PTR(ret); +} + +/** + * msm_gem_vm_close() - Close a VM + * @gpuvm: The VM to close + * + * Called when the drm device file is closed, to tear down VM related resources + * (which will drop refcounts to GEM objects that were still mapped into the + * VM at the time). + */ +void +msm_gem_vm_close(struct drm_gpuvm *gpuvm) +{ + struct msm_gem_vm *vm = to_msm_vm(gpuvm); + struct drm_gpuva *vma, *tmp; + struct drm_exec exec; + + /* + * For kernel managed VMs, the VMAs are torn down when the handle is + * closed, so nothing more to do. + */ + if (vm->managed) + return; + + if (vm->last_fence) + dma_fence_wait(vm->last_fence, false); + + /* Kill the scheduler now, so we aren't racing with it for cleanup: */ + drm_sched_stop(&vm->sched, NULL); + drm_sched_fini(&vm->sched); + + /* Tear down any remaining mappings: */ + drm_exec_init(&exec, 0, 2); + drm_exec_until_all_locked (&exec) { + drm_exec_lock_obj(&exec, drm_gpuvm_resv_obj(gpuvm)); + drm_exec_retry_on_contention(&exec); + + drm_gpuvm_for_each_va_safe (vma, tmp, gpuvm) { + struct drm_gem_object *obj = vma->gem.obj; + + /* + * MSM_BO_NO_SHARE objects share the same resv as the + * VM, in which case the obj is already locked: + */ + if (obj && (obj->resv == drm_gpuvm_resv(gpuvm))) + obj = NULL; + + if (obj) { + drm_exec_lock_obj(&exec, obj); + drm_exec_retry_on_contention(&exec); + } + + msm_gem_vma_unmap(vma, "close"); + msm_gem_vma_close(vma); + + if (obj) { + drm_exec_unlock_obj(&exec, obj); + } + } + } + drm_exec_fini(&exec); +} + + +static struct msm_vm_bind_job * +vm_bind_job_create(struct drm_device *dev, struct drm_file *file, + struct msm_gpu_submitqueue *queue, uint32_t nr_ops) +{ + struct msm_vm_bind_job *job; + uint64_t sz; + int ret; + + sz = struct_size(job, ops, nr_ops); + + if (sz > SIZE_MAX) + return ERR_PTR(-ENOMEM); + + job = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN); + if (!job) return ERR_PTR(-ENOMEM); - spin_lock_init(&aspace->lock); - aspace->name = name; - aspace->mmu = mmu; - aspace->va_start = va_start; - aspace->va_size = size; + ret = drm_sched_job_init(&job->base, queue->entity, 1, queue, + file->client_id); + if (ret) { + kfree(job); + return ERR_PTR(ret); + } + + job->vm = msm_context_vm(dev, queue->ctx); + job->queue = queue; + INIT_LIST_HEAD(&job->vm_ops); + + return job; +} + +static bool invalid_alignment(uint64_t addr) +{ + /* + * Technically this is about GPU alignment, not CPU alignment. But + * I've not seen any qcom SoC where the SMMU does not support the + * CPU's smallest page size. + */ + return !PAGE_ALIGNED(addr); +} + +static int +lookup_op(struct msm_vm_bind_job *job, const struct drm_msm_vm_bind_op *op) +{ + struct drm_device *dev = job->vm->drm; + struct msm_drm_private *priv = dev->dev_private; + int i = job->nr_ops++; + int ret = 0; + + job->ops[i].op = op->op; + job->ops[i].handle = op->handle; + job->ops[i].obj_offset = op->obj_offset; + job->ops[i].iova = op->iova; + job->ops[i].range = op->range; + job->ops[i].flags = op->flags; + + if (op->flags & ~MSM_VM_BIND_OP_FLAGS) + ret = UERR(EINVAL, dev, "invalid flags: %x\n", op->flags); + + if (invalid_alignment(op->iova)) + ret = UERR(EINVAL, dev, "invalid address: %016llx\n", op->iova); + + if (invalid_alignment(op->obj_offset)) + ret = UERR(EINVAL, dev, "invalid bo_offset: %016llx\n", op->obj_offset); + + if (invalid_alignment(op->range)) + ret = UERR(EINVAL, dev, "invalid range: %016llx\n", op->range); + + if (!drm_gpuvm_range_valid(job->vm, op->iova, op->range)) + ret = UERR(EINVAL, dev, "invalid range: %016llx, %016llx\n", op->iova, op->range); + + /* + * MAP must specify a valid handle. But the handle MBZ for + * UNMAP or MAP_NULL. + */ + if (op->op == MSM_VM_BIND_OP_MAP) { + if (!op->handle) + ret = UERR(EINVAL, dev, "invalid handle\n"); + } else if (op->handle) { + ret = UERR(EINVAL, dev, "handle must be zero\n"); + } + + switch (op->op) { + case MSM_VM_BIND_OP_MAP: + case MSM_VM_BIND_OP_MAP_NULL: + case MSM_VM_BIND_OP_UNMAP: + break; + default: + ret = UERR(EINVAL, dev, "invalid op: %u\n", op->op); + break; + } + + if ((op->op == MSM_VM_BIND_OP_MAP_NULL) && + !adreno_smmu_has_prr(priv->gpu)) { + ret = UERR(EINVAL, dev, "PRR not supported\n"); + } + + return ret; +} + +/* + * ioctl parsing, parameter validation, and GEM handle lookup + */ +static int +vm_bind_job_lookup_ops(struct msm_vm_bind_job *job, struct drm_msm_vm_bind *args, + struct drm_file *file, int *nr_bos) +{ + struct drm_device *dev = job->vm->drm; + int ret = 0; + int cnt = 0; + int i = -1; + + if (args->nr_ops == 1) { + /* Single op case, the op is inlined: */ + ret = lookup_op(job, &args->op); + } else { + for (unsigned i = 0; i < args->nr_ops; i++) { + struct drm_msm_vm_bind_op op; + void __user *userptr = + u64_to_user_ptr(args->ops + (i * sizeof(op))); + + /* make sure we don't have garbage flags, in case we hit + * error path before flags is initialized: + */ + job->ops[i].flags = 0; + + if (copy_from_user(&op, userptr, sizeof(op))) { + ret = -EFAULT; + break; + } + + ret = lookup_op(job, &op); + if (ret) + break; + } + } + + if (ret) { + job->nr_ops = 0; + goto out; + } + + spin_lock(&file->table_lock); + + for (i = 0; i < args->nr_ops; i++) { + struct msm_vm_bind_op *op = &job->ops[i]; + struct drm_gem_object *obj; + + if (!op->handle) { + op->obj = NULL; + continue; + } + + /* + * normally use drm_gem_object_lookup(), but for bulk lookup + * all under single table_lock just hit object_idr directly: + */ + obj = idr_find(&file->object_idr, op->handle); + if (!obj) { + ret = UERR(EINVAL, dev, "invalid handle %u at index %u\n", op->handle, i); + goto out_unlock; + } + + drm_gem_object_get(obj); + + op->obj = obj; + cnt++; + + if ((op->range + op->obj_offset) > obj->size) { + ret = UERR(EINVAL, dev, "invalid range: %016llx + %016llx > %016zx\n", + op->range, op->obj_offset, obj->size); + goto out_unlock; + } + } + + *nr_bos = cnt; + +out_unlock: + spin_unlock(&file->table_lock); + + if (ret) { + for (; i >= 0; i--) { + struct msm_vm_bind_op *op = &job->ops[i]; + + if (!op->obj) + continue; + + drm_gem_object_put(op->obj); + op->obj = NULL; + } + } +out: + return ret; +} + +static void +prealloc_count(struct msm_vm_bind_job *job, + struct msm_vm_bind_op *first, + struct msm_vm_bind_op *last) +{ + struct msm_mmu *mmu = to_msm_vm(job->vm)->mmu; + + if (!first) + return; + + uint64_t start_iova = first->iova; + uint64_t end_iova = last->iova + last->range; + + mmu->funcs->prealloc_count(mmu, &job->prealloc, start_iova, end_iova - start_iova); +} + +static bool +ops_are_same_pte(struct msm_vm_bind_op *first, struct msm_vm_bind_op *next) +{ + /* + * Last level pte covers 2MB.. so we should merge two ops, from + * the PoV of figuring out how much pgtable pages to pre-allocate + * if they land in the same 2MB range: + */ + uint64_t pte_mask = ~(SZ_2M - 1); + return ((first->iova + first->range) & pte_mask) == (next->iova & pte_mask); +} + +/* + * Determine the amount of memory to prealloc for pgtables. For sparse images, + * in particular, userspace plays some tricks with the order of page mappings + * to get the desired swizzle pattern, resulting in a large # of tiny MAP ops. + * So detect when multiple MAP operations are physically contiguous, and count + * them as a single mapping. Otherwise the prealloc_count() will not realize + * they can share pagetable pages and vastly overcount. + */ +static int +vm_bind_prealloc_count(struct msm_vm_bind_job *job) +{ + struct msm_vm_bind_op *first = NULL, *last = NULL; + struct msm_gem_vm *vm = to_msm_vm(job->vm); + int ret; + + for (int i = 0; i < job->nr_ops; i++) { + struct msm_vm_bind_op *op = &job->ops[i]; + + /* We only care about MAP/MAP_NULL: */ + if (op->op == MSM_VM_BIND_OP_UNMAP) + continue; + + /* + * If op is contiguous with last in the current range, then + * it becomes the new last in the range and we continue + * looping: + */ + if (last && ops_are_same_pte(last, op)) { + last = op; + continue; + } + + /* + * If op is not contiguous with the current range, flush + * the current range and start anew: + */ + prealloc_count(job, first, last); + first = last = op; + } + + /* Flush the remaining range: */ + prealloc_count(job, first, last); + + /* + * Now that we know the needed amount to pre-alloc, throttle on pending + * VM_BIND jobs if we already have too much pre-alloc memory in flight + */ + ret = wait_event_interruptible( + vm->prealloc_throttle.wait, + atomic_read(&vm->prealloc_throttle.in_flight) <= 1024); + if (ret) + return ret; + + atomic_add(job->prealloc.count, &vm->prealloc_throttle.in_flight); + + return 0; +} + +/* + * Lock VM and GEM objects + */ +static int +vm_bind_job_lock_objects(struct msm_vm_bind_job *job, struct drm_exec *exec) +{ + int ret; + + /* Lock VM and objects: */ + drm_exec_until_all_locked (exec) { + ret = drm_exec_lock_obj(exec, drm_gpuvm_resv_obj(job->vm)); + drm_exec_retry_on_contention(exec); + if (ret) + return ret; + + for (unsigned i = 0; i < job->nr_ops; i++) { + const struct msm_vm_bind_op *op = &job->ops[i]; + + switch (op->op) { + case MSM_VM_BIND_OP_UNMAP: + ret = drm_gpuvm_sm_unmap_exec_lock(job->vm, exec, + op->iova, + op->obj_offset); + break; + case MSM_VM_BIND_OP_MAP: + case MSM_VM_BIND_OP_MAP_NULL: { + struct drm_gpuvm_map_req map_req = { + .map.va.addr = op->iova, + .map.va.range = op->range, + .map.gem.obj = op->obj, + .map.gem.offset = op->obj_offset, + }; + + ret = drm_gpuvm_sm_map_exec_lock(job->vm, exec, 1, &map_req); + break; + } + default: + /* + * lookup_op() should have already thrown an error for + * invalid ops + */ + WARN_ON("unreachable"); + } + + drm_exec_retry_on_contention(exec); + if (ret) + return ret; + } + } + + return 0; +} + +/* + * Pin GEM objects, ensuring that we have backing pages. Pinning will move + * the object to the pinned LRU so that the shrinker knows to first consider + * other objects for evicting. + */ +static int +vm_bind_job_pin_objects(struct msm_vm_bind_job *job) +{ + struct drm_gem_object *obj; + + /* + * First loop, before holding the LRU lock, avoids holding the + * LRU lock while calling msm_gem_pin_vma_locked (which could + * trigger get_pages()) + */ + job_foreach_bo (obj, job) { + struct page **pages; + + pages = msm_gem_get_pages_locked(obj, MSM_MADV_WILLNEED); + if (IS_ERR(pages)) + return PTR_ERR(pages); + } + + struct msm_drm_private *priv = job->vm->drm->dev_private; + + /* + * A second loop while holding the LRU lock (a) avoids acquiring/dropping + * the LRU lock for each individual bo, while (b) avoiding holding the + * LRU lock while calling msm_gem_pin_vma_locked() (which could trigger + * get_pages() which could trigger reclaim.. and if we held the LRU lock + * could trigger deadlock with the shrinker). + */ + mutex_lock(&priv->lru.lock); + job_foreach_bo (obj, job) + msm_gem_pin_obj_locked(obj); + mutex_unlock(&priv->lru.lock); + + job->bos_pinned = true; + + return 0; +} + +/* + * Unpin GEM objects. Normally this is done after the bind job is run. + */ +static void +vm_bind_job_unpin_objects(struct msm_vm_bind_job *job) +{ + struct drm_gem_object *obj; + + if (!job->bos_pinned) + return; + + job_foreach_bo (obj, job) + msm_gem_unpin_locked(obj); + + job->bos_pinned = false; +} + +/* + * Pre-allocate pgtable memory, and translate the VM bind requests into a + * sequence of pgtable updates to be applied asynchronously. + */ +static int +vm_bind_job_prepare(struct msm_vm_bind_job *job) +{ + struct msm_gem_vm *vm = to_msm_vm(job->vm); + struct msm_mmu *mmu = vm->mmu; + int ret; + + ret = mmu->funcs->prealloc_allocate(mmu, &job->prealloc); + if (ret) + return ret; + + for (unsigned i = 0; i < job->nr_ops; i++) { + const struct msm_vm_bind_op *op = &job->ops[i]; + struct op_arg arg = { + .job = job, + .op = op, + }; + + switch (op->op) { + case MSM_VM_BIND_OP_UNMAP: + ret = drm_gpuvm_sm_unmap(job->vm, &arg, op->iova, + op->range); + break; + case MSM_VM_BIND_OP_MAP: + if (op->flags & MSM_VM_BIND_OP_DUMP) + arg.flags |= MSM_VMA_DUMP; + fallthrough; + case MSM_VM_BIND_OP_MAP_NULL: { + struct drm_gpuvm_map_req map_req = { + .map.va.addr = op->iova, + .map.va.range = op->range, + .map.gem.obj = op->obj, + .map.gem.offset = op->obj_offset, + }; + + ret = drm_gpuvm_sm_map(job->vm, &arg, &map_req); + break; + } + default: + /* + * lookup_op() should have already thrown an error for + * invalid ops + */ + BUG_ON("unreachable"); + } + + if (ret) { + /* + * If we've already started modifying the vm, we can't + * adequetly describe to userspace the intermediate + * state the vm is in. So throw up our hands! + */ + if (i > 0) + msm_gem_vm_unusable(job->vm); + return ret; + } + } + + return 0; +} + +/* + * Attach fences to the GEM objects being bound. This will signify to + * the shrinker that they are busy even after dropping the locks (ie. + * drm_exec_fini()) + */ +static void +vm_bind_job_attach_fences(struct msm_vm_bind_job *job) +{ + for (unsigned i = 0; i < job->nr_ops; i++) { + struct drm_gem_object *obj = job->ops[i].obj; + + if (!obj) + continue; + + dma_resv_add_fence(obj->resv, job->fence, + DMA_RESV_USAGE_KERNEL); + } +} + +int +msm_ioctl_vm_bind(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct msm_drm_private *priv = dev->dev_private; + struct drm_msm_vm_bind *args = data; + struct msm_context *ctx = file->driver_priv; + struct msm_vm_bind_job *job = NULL; + struct msm_gpu *gpu = priv->gpu; + struct msm_gpu_submitqueue *queue; + struct msm_syncobj_post_dep *post_deps = NULL; + struct drm_syncobj **syncobjs_to_reset = NULL; + struct sync_file *sync_file = NULL; + struct dma_fence *fence; + int out_fence_fd = -1; + int ret, nr_bos = 0; + unsigned i; + + if (!gpu) + return -ENXIO; + + /* + * Maybe we could allow just UNMAP ops? OTOH userspace should just + * immediately close the device file and all will be torn down. + */ + if (to_msm_vm(msm_context_vm(dev, ctx))->unusable) + return UERR(EPIPE, dev, "context is unusable"); + + /* + * Technically, you cannot create a VM_BIND submitqueue in the first + * place, if you haven't opted in to VM_BIND context. But it is + * cleaner / less confusing, to check this case directly. + */ + if (!msm_context_is_vmbind(ctx)) + return UERR(EINVAL, dev, "context does not support vmbind"); + + if (args->flags & ~MSM_VM_BIND_FLAGS) + return UERR(EINVAL, dev, "invalid flags"); + + queue = msm_submitqueue_get(ctx, args->queue_id); + if (!queue) + return -ENOENT; + + if (!(queue->flags & MSM_SUBMITQUEUE_VM_BIND)) { + ret = UERR(EINVAL, dev, "Invalid queue type"); + goto out_post_unlock; + } + + if (args->flags & MSM_VM_BIND_FENCE_FD_OUT) { + out_fence_fd = get_unused_fd_flags(O_CLOEXEC); + if (out_fence_fd < 0) { + ret = out_fence_fd; + goto out_post_unlock; + } + } + + job = vm_bind_job_create(dev, file, queue, args->nr_ops); + if (IS_ERR(job)) { + ret = PTR_ERR(job); + goto out_post_unlock; + } + + ret = mutex_lock_interruptible(&queue->lock); + if (ret) + goto out_post_unlock; + + if (args->flags & MSM_VM_BIND_FENCE_FD_IN) { + struct dma_fence *in_fence; + + in_fence = sync_file_get_fence(args->fence_fd); + + if (!in_fence) { + ret = UERR(EINVAL, dev, "invalid in-fence"); + goto out_unlock; + } + + ret = drm_sched_job_add_dependency(&job->base, in_fence); + if (ret) + goto out_unlock; + } + + if (args->in_syncobjs > 0) { + syncobjs_to_reset = msm_syncobj_parse_deps(dev, &job->base, + file, args->in_syncobjs, + args->nr_in_syncobjs, + args->syncobj_stride); + if (IS_ERR(syncobjs_to_reset)) { + ret = PTR_ERR(syncobjs_to_reset); + goto out_unlock; + } + } + + if (args->out_syncobjs > 0) { + post_deps = msm_syncobj_parse_post_deps(dev, file, + args->out_syncobjs, + args->nr_out_syncobjs, + args->syncobj_stride); + if (IS_ERR(post_deps)) { + ret = PTR_ERR(post_deps); + goto out_unlock; + } + } + + ret = vm_bind_job_lookup_ops(job, args, file, &nr_bos); + if (ret) + goto out_unlock; + + ret = vm_bind_prealloc_count(job); + if (ret) + goto out_unlock; + + struct drm_exec exec; + unsigned flags = DRM_EXEC_IGNORE_DUPLICATES | DRM_EXEC_INTERRUPTIBLE_WAIT; + drm_exec_init(&exec, flags, nr_bos + 1); - drm_mm_init(&aspace->mm, va_start, size); + ret = vm_bind_job_lock_objects(job, &exec); + if (ret) + goto out; + + ret = vm_bind_job_pin_objects(job); + if (ret) + goto out; + + ret = vm_bind_job_prepare(job); + if (ret) + goto out; + + drm_sched_job_arm(&job->base); + + job->fence = dma_fence_get(&job->base.s_fence->finished); + + if (args->flags & MSM_VM_BIND_FENCE_FD_OUT) { + sync_file = sync_file_create(job->fence); + if (!sync_file) + ret = -ENOMEM; + } + + if (ret) + goto out; + + vm_bind_job_attach_fences(job); + + /* + * The job can be free'd (and fence unref'd) at any point after + * drm_sched_entity_push_job(), so we need to hold our own ref + */ + fence = dma_fence_get(job->fence); - kref_init(&aspace->kref); + drm_sched_entity_push_job(&job->base); - return aspace; + msm_syncobj_reset(syncobjs_to_reset, args->nr_in_syncobjs); + msm_syncobj_process_post_deps(post_deps, args->nr_out_syncobjs, fence); + + dma_fence_put(fence); + +out: + if (ret) + vm_bind_job_unpin_objects(job); + + drm_exec_fini(&exec); +out_unlock: + mutex_unlock(&queue->lock); +out_post_unlock: + if (ret) { + if (out_fence_fd >= 0) + put_unused_fd(out_fence_fd); + if (sync_file) + fput(sync_file->file); + } else if (sync_file) { + fd_install(out_fence_fd, sync_file->file); + args->fence_fd = out_fence_fd; + } + + if (!IS_ERR_OR_NULL(job)) { + if (ret) + msm_vma_job_free(&job->base); + } else { + /* + * If the submit hasn't yet taken ownership of the queue + * then we need to drop the reference ourself: + */ + msm_submitqueue_put(queue); + } + + if (!IS_ERR_OR_NULL(post_deps)) { + for (i = 0; i < args->nr_out_syncobjs; ++i) { + kfree(post_deps[i].chain); + drm_syncobj_put(post_deps[i].syncobj); + } + kfree(post_deps); + } + + if (!IS_ERR_OR_NULL(syncobjs_to_reset)) { + for (i = 0; i < args->nr_in_syncobjs; ++i) { + if (syncobjs_to_reset[i]) + drm_syncobj_put(syncobjs_to_reset[i]); + } + kfree(syncobjs_to_reset); + } + + return ret; } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 0d4a3744cfcb..995549d0bbbc 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -148,7 +148,7 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu) return 0; } -void msm_gpu_show_fdinfo(struct msm_gpu *gpu, struct msm_file_private *ctx, +void msm_gpu_show_fdinfo(struct msm_gpu *gpu, struct msm_context *ctx, struct drm_printer *p) { drm_printf(p, "drm-engine-gpu:\t%llu ns\n", ctx->elapsed_ns); @@ -197,8 +197,7 @@ static ssize_t msm_gpu_devcoredump_read(char *buffer, loff_t offset, drm_printf(&p, "---\n"); drm_printf(&p, "kernel: " UTS_RELEASE "\n"); drm_printf(&p, "module: " KBUILD_MODNAME "\n"); - drm_printf(&p, "time: %lld.%09ld\n", - state->time.tv_sec, state->time.tv_nsec); + drm_printf(&p, "time: %ptSp\n", &state->time); if (state->comm) drm_printf(&p, "comm: %s\n", state->comm); if (state->cmd) @@ -219,13 +218,14 @@ static void msm_gpu_devcoredump_free(void *data) } static void msm_gpu_crashstate_get_bo(struct msm_gpu_state *state, - struct drm_gem_object *obj, u64 iova, bool full) + struct drm_gem_object *obj, u64 iova, + bool full, size_t offset, size_t size) { struct msm_gpu_state_bo *state_bo = &state->bos[state->nr_bos]; struct msm_gem_object *msm_obj = to_msm_bo(obj); /* Don't record write only objects */ - state_bo->size = obj->size; + state_bo->size = size; state_bo->flags = msm_obj->flags; state_bo->iova = iova; @@ -236,28 +236,134 @@ static void msm_gpu_crashstate_get_bo(struct msm_gpu_state *state, if (full) { void *ptr; - state_bo->data = kvmalloc(obj->size, GFP_KERNEL); + state_bo->data = kvmalloc(size, GFP_KERNEL); if (!state_bo->data) goto out; - msm_gem_lock(obj); ptr = msm_gem_get_vaddr_active(obj); - msm_gem_unlock(obj); if (IS_ERR(ptr)) { kvfree(state_bo->data); state_bo->data = NULL; goto out; } - memcpy(state_bo->data, ptr, obj->size); - msm_gem_put_vaddr(obj); + memcpy(state_bo->data, ptr + offset, size); + msm_gem_put_vaddr_locked(obj); } out: state->nr_bos++; } +static void crashstate_get_bos(struct msm_gpu_state *state, struct msm_gem_submit *submit) +{ + extern bool rd_full; + + if (msm_context_is_vmbind(submit->queue->ctx)) { + struct drm_exec exec; + struct drm_gpuva *vma; + unsigned cnt = 0; + + drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0); + drm_exec_until_all_locked(&exec) { + cnt = 0; + + drm_exec_lock_obj(&exec, drm_gpuvm_resv_obj(submit->vm)); + drm_exec_retry_on_contention(&exec); + + drm_gpuvm_for_each_va (vma, submit->vm) { + if (!vma->gem.obj) + continue; + + cnt++; + drm_exec_lock_obj(&exec, vma->gem.obj); + drm_exec_retry_on_contention(&exec); + } + + } + + drm_gpuvm_for_each_va (vma, submit->vm) + cnt++; + + state->bos = kcalloc(cnt, sizeof(struct msm_gpu_state_bo), GFP_KERNEL); + + if (state->bos) + drm_gpuvm_for_each_va(vma, submit->vm) { + bool dump = rd_full || (vma->flags & MSM_VMA_DUMP); + + /* Skip MAP_NULL/PRR VMAs: */ + if (!vma->gem.obj) + continue; + + msm_gpu_crashstate_get_bo(state, vma->gem.obj, vma->va.addr, + dump, vma->gem.offset, vma->va.range); + } + + drm_exec_fini(&exec); + } else { + state->bos = kcalloc(submit->nr_bos, + sizeof(struct msm_gpu_state_bo), GFP_KERNEL); + + for (int i = 0; state->bos && i < submit->nr_bos; i++) { + struct drm_gem_object *obj = submit->bos[i].obj; + bool dump = rd_full || (submit->bos[i].flags & MSM_SUBMIT_BO_DUMP); + + msm_gem_lock(obj); + msm_gpu_crashstate_get_bo(state, obj, submit->bos[i].iova, + dump, 0, obj->size); + msm_gem_unlock(obj); + } + } +} + +static void crashstate_get_vm_logs(struct msm_gpu_state *state, struct msm_gem_vm *vm) +{ + uint32_t vm_log_len = (1 << vm->log_shift); + uint32_t vm_log_mask = vm_log_len - 1; + int first; + + /* Bail if no log, or empty log: */ + if (!vm->log || !vm->log[0].op) + return; + + mutex_lock(&vm->mmu_lock); + + /* + * log_idx is the next entry to overwrite, meaning it is the oldest, or + * first, entry (other than the special case handled below where the + * log hasn't wrapped around yet) + */ + first = vm->log_idx; + + if (!vm->log[first].op) { + /* + * If the next log entry has not been written yet, then only + * entries 0 to idx-1 are valid (ie. we haven't wrapped around + * yet) + */ + state->nr_vm_logs = MAX(0, first - 1); + first = 0; + } else { + state->nr_vm_logs = vm_log_len; + } + + state->vm_logs = kmalloc_array( + state->nr_vm_logs, sizeof(vm->log[0]), GFP_KERNEL); + if (!state->vm_logs) { + state->nr_vm_logs = 0; + } + + for (int i = 0; i < state->nr_vm_logs; i++) { + int idx = (i + first) & vm_log_mask; + + state->vm_logs[i] = vm->log[idx]; + } + + mutex_unlock(&vm->mmu_lock); +} + static void msm_gpu_crashstate_capture(struct msm_gpu *gpu, - struct msm_gem_submit *submit, char *comm, char *cmd) + struct msm_gem_submit *submit, struct msm_gpu_fault_info *fault_info, + char *comm, char *cmd) { struct msm_gpu_state *state; @@ -276,19 +382,21 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu, /* Fill in the additional crash state information */ state->comm = kstrdup(comm, GFP_KERNEL); state->cmd = kstrdup(cmd, GFP_KERNEL); - state->fault_info = gpu->fault_info; + if (fault_info) + state->fault_info = *fault_info; - if (submit) { - int i; + if (submit && state->fault_info.ttbr0) { + struct msm_gpu_fault_info *info = &state->fault_info; + struct msm_mmu *mmu = to_msm_vm(submit->vm)->mmu; - state->bos = kcalloc(submit->nr_bos, - sizeof(struct msm_gpu_state_bo), GFP_KERNEL); + msm_iommu_pagetable_params(mmu, &info->pgtbl_ttbr0, + &info->asid); + msm_iommu_pagetable_walk(mmu, info->iova, info->ptes); + } - for (i = 0; state->bos && i < submit->nr_bos; i++) { - msm_gpu_crashstate_get_bo(state, submit->bos[i].obj, - submit->bos[i].iova, - should_dump(submit, i)); - } + if (submit) { + crashstate_get_vm_logs(state, to_msm_vm(submit->vm)); + crashstate_get_bos(state, submit); } /* Set the active crash state to be dumped on failure */ @@ -299,7 +407,8 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu, } #else static void msm_gpu_crashstate_capture(struct msm_gpu *gpu, - struct msm_gem_submit *submit, char *comm, char *cmd) + struct msm_gem_submit *submit, struct msm_gpu_fault_info *fault_info, + char *comm, char *cmd) { } #endif @@ -330,7 +439,7 @@ static void retire_submits(struct msm_gpu *gpu); static void get_comm_cmdline(struct msm_gem_submit *submit, char **comm, char **cmd) { - struct msm_file_private *ctx = submit->queue->ctx; + struct msm_context *ctx = submit->queue->ctx; struct task_struct *task; WARN_ON(!mutex_is_locked(&submit->gpu->lock)); @@ -360,6 +469,7 @@ static void recover_worker(struct kthread_work *work) struct msm_gem_submit *submit; struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu); char *comm = NULL, *cmd = NULL; + struct task_struct *task; int i; mutex_lock(&gpu->lock); @@ -377,8 +487,24 @@ static void recover_worker(struct kthread_work *work) /* Increment the fault counts */ submit->queue->faults++; - if (submit->aspace) - submit->aspace->faults++; + + task = get_pid_task(submit->pid, PIDTYPE_PID); + if (!task) + gpu->global_faults++; + else { + struct msm_gem_vm *vm = to_msm_vm(submit->vm); + + vm->faults++; + + /* + * If userspace has opted-in to VM_BIND (and therefore userspace + * management of the VM), faults mark the VM as unusable. This + * matches vulkan expectations (vulkan is the main target for + * VM_BIND). + */ + if (!vm->managed) + msm_gem_vm_unusable(submit->vm); + } get_comm_cmdline(submit, &comm, &cmd); @@ -396,7 +522,7 @@ static void recover_worker(struct kthread_work *work) /* Record the crash state */ pm_runtime_get_sync(&gpu->pdev->dev); - msm_gpu_crashstate_capture(gpu, submit, comm, cmd); + msm_gpu_crashstate_capture(gpu, submit, NULL, comm, cmd); kfree(cmd); kfree(comm); @@ -436,8 +562,15 @@ static void recover_worker(struct kthread_work *work) unsigned long flags; spin_lock_irqsave(&ring->submit_lock, flags); - list_for_each_entry(submit, &ring->submits, node) + list_for_each_entry(submit, &ring->submits, node) { + /* + * If the submit uses an unusable vm make sure + * we don't actually run it + */ + if (to_msm_vm(submit->vm)->unusable) + submit->nr_cmds = 0; gpu->funcs->submit(gpu, submit); + } spin_unlock_irqrestore(&ring->submit_lock, flags); } } @@ -450,9 +583,8 @@ out_unlock: msm_gpu_retire(gpu); } -static void fault_worker(struct kthread_work *work) +void msm_gpu_fault_crashstate_capture(struct msm_gpu *gpu, struct msm_gpu_fault_info *fault_info) { - struct msm_gpu *gpu = container_of(work, struct msm_gpu, fault_work); struct msm_gem_submit *submit; struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu); char *comm = NULL, *cmd = NULL; @@ -475,16 +607,13 @@ static void fault_worker(struct kthread_work *work) /* Record the crash state */ pm_runtime_get_sync(&gpu->pdev->dev); - msm_gpu_crashstate_capture(gpu, submit, comm, cmd); + msm_gpu_crashstate_capture(gpu, submit, fault_info, comm, cmd); pm_runtime_put_sync(&gpu->pdev->dev); kfree(cmd); kfree(comm); resume_smmu: - memset(&gpu->fault_info, 0, sizeof(gpu->fault_info)); - gpu->aspace->mmu->funcs->resume_translation(gpu->aspace->mmu); - mutex_unlock(&gpu->lock); } @@ -512,7 +641,7 @@ static bool made_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring) static void hangcheck_handler(struct timer_list *t) { - struct msm_gpu *gpu = from_timer(gpu, t, hangcheck_timer); + struct msm_gpu *gpu = timer_container_of(gpu, t, hangcheck_timer); struct drm_device *dev = gpu->dev; struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu); uint32_t fence = ring->memptrs->fence; @@ -820,10 +949,12 @@ static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu) } /* Return a new address space for a msm_drm_private instance */ -struct msm_gem_address_space * -msm_gpu_create_private_address_space(struct msm_gpu *gpu, struct task_struct *task) +struct drm_gpuvm * +msm_gpu_create_private_vm(struct msm_gpu *gpu, struct task_struct *task, + bool kernel_managed) { - struct msm_gem_address_space *aspace = NULL; + struct drm_gpuvm *vm = NULL; + if (!gpu) return NULL; @@ -831,16 +962,16 @@ msm_gpu_create_private_address_space(struct msm_gpu *gpu, struct task_struct *ta * If the target doesn't support private address spaces then return * the global one */ - if (gpu->funcs->create_private_address_space) { - aspace = gpu->funcs->create_private_address_space(gpu); - if (!IS_ERR(aspace)) - aspace->pid = get_pid(task_pid(task)); + if (gpu->funcs->create_private_vm) { + vm = gpu->funcs->create_private_vm(gpu, kernel_managed); + if (!IS_ERR(vm)) + to_msm_vm(vm)->pid = get_pid(task_pid(task)); } - if (IS_ERR_OR_NULL(aspace)) - aspace = msm_gem_address_space_get(gpu->aspace); + if (IS_ERR_OR_NULL(vm)) + vm = drm_gpuvm_get(gpu->vm); - return aspace; + return vm; } int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, @@ -859,7 +990,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, gpu->funcs = funcs; gpu->name = name; - gpu->worker = kthread_create_worker(0, "gpu-worker"); + gpu->worker = kthread_run_worker(0, "gpu-worker"); if (IS_ERR(gpu->worker)) { ret = PTR_ERR(gpu->worker); gpu->worker = NULL; @@ -873,7 +1004,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, init_waitqueue_head(&gpu->retire_event); kthread_init_work(&gpu->retire_work, retire_worker); kthread_init_work(&gpu->recover_work, recover_worker); - kthread_init_work(&gpu->fault_work, fault_worker); priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD; @@ -935,19 +1065,15 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, msm_devfreq_init(gpu); - - gpu->aspace = gpu->funcs->create_address_space(gpu, pdev); - - if (gpu->aspace == NULL) - DRM_DEV_INFO(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name); - else if (IS_ERR(gpu->aspace)) { - ret = PTR_ERR(gpu->aspace); + gpu->vm = gpu->funcs->create_vm(gpu, pdev); + if (IS_ERR(gpu->vm)) { + ret = PTR_ERR(gpu->vm); goto fail; } memptrs = msm_gem_kernel_new(drm, sizeof(struct msm_rbmemptrs) * nr_rings, - check_apriv(gpu, MSM_BO_WC), gpu->aspace, &gpu->memptrs_bo, + check_apriv(gpu, MSM_BO_WC), gpu->vm, &gpu->memptrs_bo, &memptrs_iova); if (IS_ERR(memptrs)) { @@ -991,7 +1117,7 @@ fail: gpu->rb[i] = NULL; } - msm_gem_kernel_put(gpu->memptrs_bo, gpu->aspace); + msm_gem_kernel_put(gpu->memptrs_bo, gpu->vm); platform_set_drvdata(pdev, NULL); return ret; @@ -1008,11 +1134,12 @@ void msm_gpu_cleanup(struct msm_gpu *gpu) gpu->rb[i] = NULL; } - msm_gem_kernel_put(gpu->memptrs_bo, gpu->aspace); + msm_gem_kernel_put(gpu->memptrs_bo, gpu->vm); - if (!IS_ERR_OR_NULL(gpu->aspace)) { - gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu); - msm_gem_address_space_put(gpu->aspace); + if (!IS_ERR_OR_NULL(gpu->vm)) { + struct msm_mmu *mmu = to_msm_vm(gpu->vm)->mmu; + mmu->funcs->detach(mmu); + drm_gpuvm_put(gpu->vm); } if (gpu->worker) { diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 7cabc8480d7c..2894fc118485 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -16,13 +16,15 @@ #include "msm_drv.h" #include "msm_fence.h" +#include "msm_gpu_trace.h" #include "msm_ringbuffer.h" #include "msm_gem.h" struct msm_gem_submit; +struct msm_gem_vm_log_entry; struct msm_gpu_perfcntr; struct msm_gpu_state; -struct msm_file_private; +struct msm_context; struct msm_gpu_config { const char *ioname; @@ -44,9 +46,9 @@ struct msm_gpu_config { * + z180_gpu */ struct msm_gpu_funcs { - int (*get_param)(struct msm_gpu *gpu, struct msm_file_private *ctx, + int (*get_param)(struct msm_gpu *gpu, struct msm_context *ctx, uint32_t param, uint64_t *value, uint32_t *len); - int (*set_param)(struct msm_gpu *gpu, struct msm_file_private *ctx, + int (*set_param)(struct msm_gpu *gpu, struct msm_context *ctx, uint32_t param, uint64_t value, uint32_t len); int (*hw_init)(struct msm_gpu *gpu); @@ -78,10 +80,8 @@ struct msm_gpu_funcs { /* note: gpu_set_freq() can assume that we have been pm_resumed */ void (*gpu_set_freq)(struct msm_gpu *gpu, struct dev_pm_opp *opp, bool suspended); - struct msm_gem_address_space *(*create_address_space) - (struct msm_gpu *gpu, struct platform_device *pdev); - struct msm_gem_address_space *(*create_private_address_space) - (struct msm_gpu *gpu); + struct drm_gpuvm *(*create_vm)(struct msm_gpu *gpu, struct platform_device *pdev); + struct drm_gpuvm *(*create_private_vm)(struct msm_gpu *gpu, bool kernel_managed); uint32_t (*get_rptr)(struct msm_gpu *gpu, struct msm_ringbuffer *ring); /** @@ -92,6 +92,7 @@ struct msm_gpu_funcs { * for cmdstream that is buffered in this FIFO upstream of the CP fw. */ bool (*progress)(struct msm_gpu *gpu, struct msm_ringbuffer *ring); + void (*sysprof_setup)(struct msm_gpu *gpu); }; /* Additional state for iommu faults: */ @@ -101,6 +102,14 @@ struct msm_gpu_fault_info { int flags; const char *type; const char *block; + + /* Information about what we think/expect is the current SMMU state, + * for example expected_ttbr0 should match smmu_info.ttbr0 which + * was read back from SMMU registers. + */ + phys_addr_t pgtbl_ttbr0; + u64 ptes[4]; + int asid; }; /** @@ -228,7 +237,7 @@ struct msm_gpu { void __iomem *mmio; int irq; - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; /* Power Control: */ struct regulator *gpu_reg, *gpu_cx; @@ -245,12 +254,6 @@ struct msm_gpu { #define DRM_MSM_HANGCHECK_PROGRESS_RETRIES 3 struct timer_list hangcheck_timer; - /* Fault info for most recent iova fault: */ - struct msm_gpu_fault_info fault_info; - - /* work for handling GPU ioval faults: */ - struct kthread_work fault_work; - /* work for handling GPU recovery: */ struct kthread_work recover_work; @@ -296,6 +299,17 @@ static inline struct msm_gpu *dev_to_gpu(struct device *dev) return container_of(adreno_smmu, struct msm_gpu, adreno_smmu); } +static inline bool +adreno_smmu_has_prr(struct msm_gpu *gpu) +{ + struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(&gpu->pdev->dev); + + if (!adreno_smmu) + return false; + + return adreno_smmu && adreno_smmu->set_prr_addr; +} + /* It turns out that all targets use the same ringbuffer size */ #define MSM_GPU_RINGBUFFER_SZ SZ_32K #define MSM_GPU_RINGBUFFER_BLKSIZE 32 @@ -339,26 +353,61 @@ struct msm_gpu_perfcntr { #define NR_SCHED_PRIORITIES (1 + DRM_SCHED_PRIORITY_LOW - DRM_SCHED_PRIORITY_HIGH) /** - * struct msm_file_private - per-drm_file context - * - * @queuelock: synchronizes access to submitqueues list - * @submitqueues: list of &msm_gpu_submitqueue created by userspace - * @queueid: counter incremented each time a submitqueue is created, - * used to assign &msm_gpu_submitqueue.id - * @aspace: the per-process GPU address-space - * @ref: reference count - * @seqno: unique per process seqno + * struct msm_context - per-drm_file context */ -struct msm_file_private { +struct msm_context { + /** @queuelock: synchronizes access to submitqueues list */ rwlock_t queuelock; + + /** @submitqueues: list of &msm_gpu_submitqueue created by userspace */ struct list_head submitqueues; + + /** + * @queueid: + * + * Counter incremented each time a submitqueue is created, used to + * assign &msm_gpu_submitqueue.id + */ int queueid; - struct msm_gem_address_space *aspace; + + /** + * @closed: The device file associated with this context has been closed. + * + * Once the device is closed, any submits that have not been written + * to the ring buffer are no-op'd. + */ + bool closed; + + /** + * @userspace_managed_vm: + * + * Has userspace opted-in to userspace managed VM (ie. VM_BIND) via + * MSM_PARAM_EN_VM_BIND? + */ + bool userspace_managed_vm; + + /** + * @vm: + * + * The per-process GPU address-space. Do not access directly, use + * msm_context_vm(). + */ + struct drm_gpuvm *vm; + + /** @kref: the reference count */ struct kref ref; + + /** + * @seqno: + * + * A unique per-process sequence number. Used to detect context + * switches, without relying on keeping a, potentially dangling, + * pointer to the previous context. + */ int seqno; /** - * sysprof: + * @sysprof: * * The value of MSM_PARAM_SYSPROF set by userspace. This is * intended to be used by system profiling tools like Mesa's @@ -376,21 +425,21 @@ struct msm_file_private { int sysprof; /** - * comm: Overridden task comm, see MSM_PARAM_COMM + * @comm: Overridden task comm, see MSM_PARAM_COMM * * Accessed under msm_gpu::lock */ char *comm; /** - * cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE + * @cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE * * Accessed under msm_gpu::lock */ char *cmdline; /** - * elapsed: + * @elapsed: * * The total (cumulative) elapsed time GPU was busy with rendering * from this context in ns. @@ -398,7 +447,7 @@ struct msm_file_private { uint64_t elapsed_ns; /** - * cycles: + * @cycles: * * The total (cumulative) GPU cycles elapsed attributed to this * context. @@ -406,7 +455,7 @@ struct msm_file_private { uint64_t cycles; /** - * entities: + * @entities: * * Table of per-priority-level sched entities used by submitqueues * associated with this &drm_file. Because some userspace apps @@ -419,7 +468,7 @@ struct msm_file_private { struct drm_sched_entity *entities[NR_SCHED_PRIORITIES * MSM_GPU_MAX_RINGS]; /** - * ctx_mem: + * @ctx_mem: * * Total amount of memory of GEM buffers with handles attached for * this context. @@ -427,6 +476,24 @@ struct msm_file_private { atomic64_t ctx_mem; }; +struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx); + +/** + * msm_context_is_vm_bind() - has userspace opted in to VM_BIND? + * + * @ctx: the drm_file context + * + * See MSM_PARAM_EN_VM_BIND. If userspace is managing the VM, it can + * do sparse binding including having multiple, potentially partial, + * mappings in the VM. Therefore certain legacy uabi (ie. GET_IOVA, + * SET_IOVA) are rejected because they don't have a sensible meaning. + */ +static inline bool +msm_context_is_vmbind(struct msm_context *ctx) +{ + return ctx->userspace_managed_vm; +} + /** * msm_gpu_convert_priority - Map userspace priority to ring # and sched priority * @@ -504,13 +571,16 @@ struct msm_gpu_submitqueue { u32 ring_nr; int faults; uint32_t last_fence; - struct msm_file_private *ctx; + struct msm_context *ctx; struct list_head node; struct idr fence_idr; struct spinlock idr_lock; struct mutex lock; struct kref ref; struct drm_sched_entity *entity; + + /** @_vm_bind_entity: used for @entity pointer for VM_BIND queues */ + struct drm_sched_entity _vm_bind_entity[0]; }; struct msm_gpu_state_bo { @@ -547,22 +617,28 @@ struct msm_gpu_state { struct msm_gpu_fault_info fault_info; + int nr_vm_logs; + struct msm_gem_vm_log_entry *vm_logs; + int nr_bos; struct msm_gpu_state_bo *bos; }; static inline void gpu_write(struct msm_gpu *gpu, u32 reg, u32 data) { + trace_msm_gpu_regaccess(reg); writel(data, gpu->mmio + (reg << 2)); } static inline u32 gpu_read(struct msm_gpu *gpu, u32 reg) { + trace_msm_gpu_regaccess(reg); return readl(gpu->mmio + (reg << 2)); } static inline void gpu_rmw(struct msm_gpu *gpu, u32 reg, u32 mask, u32 or) { + trace_msm_gpu_regaccess(reg); msm_rmw(gpu->mmio + (reg << 2), mask, or); } @@ -584,7 +660,9 @@ static inline u64 gpu_read64(struct msm_gpu *gpu, u32 reg) * when the lo is read, so make sure to read the lo first to trigger * that */ + trace_msm_gpu_regaccess(reg); val = (u64) readl(gpu->mmio + (reg << 2)); + trace_msm_gpu_regaccess(reg+1); val |= ((u64) readl(gpu->mmio + ((reg + 1) << 2)) << 32); return val; @@ -592,41 +670,42 @@ static inline u64 gpu_read64(struct msm_gpu *gpu, u32 reg) static inline void gpu_write64(struct msm_gpu *gpu, u32 reg, u64 val) { + trace_msm_gpu_regaccess(reg); /* Why not a writeq here? Read the screed above */ writel(lower_32_bits(val), gpu->mmio + (reg << 2)); + trace_msm_gpu_regaccess(reg+1); writel(upper_32_bits(val), gpu->mmio + ((reg + 1) << 2)); } int msm_gpu_pm_suspend(struct msm_gpu *gpu); int msm_gpu_pm_resume(struct msm_gpu *gpu); -void msm_gpu_show_fdinfo(struct msm_gpu *gpu, struct msm_file_private *ctx, +void msm_gpu_show_fdinfo(struct msm_gpu *gpu, struct msm_context *ctx, struct drm_printer *p); -int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx); -struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx, +int msm_submitqueue_init(struct drm_device *drm, struct msm_context *ctx); +struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_context *ctx, u32 id); int msm_submitqueue_create(struct drm_device *drm, - struct msm_file_private *ctx, + struct msm_context *ctx, u32 prio, u32 flags, u32 *id); -int msm_submitqueue_query(struct drm_device *drm, struct msm_file_private *ctx, +int msm_submitqueue_query(struct drm_device *drm, struct msm_context *ctx, struct drm_msm_submitqueue_query *args); -int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id); -void msm_submitqueue_close(struct msm_file_private *ctx); +int msm_submitqueue_remove(struct msm_context *ctx, u32 id); +void msm_submitqueue_close(struct msm_context *ctx); void msm_submitqueue_destroy(struct kref *kref); -int msm_file_private_set_sysprof(struct msm_file_private *ctx, - struct msm_gpu *gpu, int sysprof); -void __msm_file_private_destroy(struct kref *kref); +int msm_context_set_sysprof(struct msm_context *ctx, struct msm_gpu *gpu, int sysprof); +void __msm_context_destroy(struct kref *kref); -static inline void msm_file_private_put(struct msm_file_private *ctx) +static inline void msm_context_put(struct msm_context *ctx) { - kref_put(&ctx->ref, __msm_file_private_destroy); + kref_put(&ctx->ref, __msm_context_destroy); } -static inline struct msm_file_private *msm_file_private_get( - struct msm_file_private *ctx) +static inline struct msm_context *msm_context_get( + struct msm_context *ctx) { kref_get(&ctx->ref); return ctx; @@ -654,12 +733,14 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs, const char *name, struct msm_gpu_config *config); -struct msm_gem_address_space * -msm_gpu_create_private_address_space(struct msm_gpu *gpu, struct task_struct *task); +struct drm_gpuvm * +msm_gpu_create_private_vm(struct msm_gpu *gpu, struct task_struct *task, + bool kernel_managed); void msm_gpu_cleanup(struct msm_gpu *gpu); struct msm_gpu *adreno_load_gpu(struct drm_device *dev); +bool adreno_has_gpu(struct device_node *node); void __init adreno_register(void); void __exit adreno_unregister(void); @@ -697,6 +778,8 @@ static inline void msm_gpu_crashstate_put(struct msm_gpu *gpu) mutex_unlock(&gpu->lock); } +void msm_gpu_fault_crashstate_capture(struct msm_gpu *gpu, struct msm_gpu_fault_info *fault_info); + /* * Simple macro to semi-cleanly add the MAP_PRIV flag for targets that can * support expanded privileges diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c index 6970b0f7f457..2e1d5c343272 100644 --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c @@ -156,6 +156,7 @@ void msm_devfreq_init(struct msm_gpu *gpu) priv->gpu_devfreq_config.downdifferential = 10; mutex_init(&df->lock); + df->suspended = true; ret = dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq, DEV_PM_QOS_MIN_FREQUENCY, 0); diff --git a/drivers/gpu/drm/msm/msm_gpu_trace.h b/drivers/gpu/drm/msm/msm_gpu_trace.h index 7f863282db0d..5417f8d389a3 100644 --- a/drivers/gpu/drm/msm/msm_gpu_trace.h +++ b/drivers/gpu/drm/msm/msm_gpu_trace.h @@ -205,6 +205,32 @@ TRACE_EVENT(msm_gpu_preemption_irq, TP_printk("preempted to %u", __entry->ring_id) ); +TRACE_EVENT(msm_mmu_prealloc_cleanup, + TP_PROTO(u32 count, u32 remaining), + TP_ARGS(count, remaining), + TP_STRUCT__entry( + __field(u32, count) + __field(u32, remaining) + ), + TP_fast_assign( + __entry->count = count; + __entry->remaining = remaining; + ), + TP_printk("count=%u, remaining=%u", __entry->count, __entry->remaining) +); + +TRACE_EVENT(msm_gpu_regaccess, + TP_PROTO(u32 offset), + TP_ARGS(offset), + TP_STRUCT__entry( + __field(u32, offset) + ), + TP_fast_assign( + __entry->offset = offset; + ), + TP_printk("offset=0x%x", __entry->offset) +); + #endif #undef TRACE_INCLUDE_PATH diff --git a/drivers/gpu/drm/msm/msm_io_utils.c b/drivers/gpu/drm/msm/msm_io_utils.c index afedd61c3e28..a6efe1eac271 100644 --- a/drivers/gpu/drm/msm/msm_io_utils.c +++ b/drivers/gpu/drm/msm/msm_io_utils.c @@ -135,8 +135,7 @@ void msm_hrtimer_work_init(struct msm_hrtimer_work *work, clockid_t clock_id, enum hrtimer_mode mode) { - hrtimer_init(&work->timer, clock_id, mode); - work->timer.function = msm_hrtimer_worktimer; + hrtimer_setup(&work->timer, msm_hrtimer_worktimer, clock_id, mode); work->worker = worker; kthread_init_work(&work->work, fn); } diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 2a94e82316f9..a188617653e8 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -6,13 +6,20 @@ #include <linux/adreno-smmu-priv.h> #include <linux/io-pgtable.h> +#include <linux/kmemleak.h> #include "msm_drv.h" +#include "msm_gpu_trace.h" #include "msm_mmu.h" struct msm_iommu { struct msm_mmu base; struct iommu_domain *domain; - atomic_t pagetables; + + struct mutex init_lock; /* protects pagetables counter and prr_page */ + int pagetables; + struct page *prr_page; + + struct kmem_cache *pt_cache; }; #define to_msm_iommu(x) container_of(x, struct msm_iommu, base) @@ -26,6 +33,9 @@ struct msm_iommu_pagetable { unsigned long pgsize_bitmap; /* Bitmap of page sizes in use */ phys_addr_t ttbr; u32 asid; + + /** @root_page_table: Stores the root page table pointer. */ + void *root_page_table; }; static struct msm_iommu_pagetable *to_pagetable(struct msm_mmu *mmu) { @@ -93,15 +103,24 @@ static int msm_iommu_pagetable_unmap(struct msm_mmu *mmu, u64 iova, { struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); struct io_pgtable_ops *ops = pagetable->pgtbl_ops; + int ret = 0; while (size) { - size_t unmapped, pgsize, count; + size_t pgsize, count; + ssize_t unmapped; pgsize = calc_pgsize(pagetable, iova, iova, size, &count); unmapped = ops->unmap_pages(ops, iova, pgsize, count, NULL); - if (!unmapped) - break; + if (unmapped <= 0) { + ret = -EINVAL; + /* + * Continue attempting to unamp the remained of the + * range, so we don't end up with some dangling + * mapped pages + */ + unmapped = PAGE_SIZE; + } iova += unmapped; size -= unmapped; @@ -109,11 +128,42 @@ static int msm_iommu_pagetable_unmap(struct msm_mmu *mmu, u64 iova, iommu_flush_iotlb_all(to_msm_iommu(pagetable->parent)->domain); - return (size == 0) ? 0 : -EINVAL; + return ret; +} + +static int msm_iommu_pagetable_map_prr(struct msm_mmu *mmu, u64 iova, size_t len, int prot) +{ + struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); + struct io_pgtable_ops *ops = pagetable->pgtbl_ops; + struct msm_iommu *iommu = to_msm_iommu(pagetable->parent); + phys_addr_t phys = page_to_phys(iommu->prr_page); + u64 addr = iova; + + while (len) { + size_t mapped = 0; + size_t size = PAGE_SIZE; + int ret; + + ret = ops->map_pages(ops, addr, phys, size, 1, prot, GFP_KERNEL, &mapped); + + /* map_pages could fail after mapping some of the pages, + * so update the counters before error handling. + */ + addr += mapped; + len -= mapped; + + if (ret) { + msm_iommu_pagetable_unmap(mmu, iova, addr - iova); + return -EINVAL; + } + } + + return 0; } static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, - struct sg_table *sgt, size_t len, int prot) + struct sg_table *sgt, size_t off, size_t len, + int prot) { struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); struct io_pgtable_ops *ops = pagetable->pgtbl_ops; @@ -121,10 +171,26 @@ static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, u64 addr = iova; unsigned int i; + if (!sgt) + return msm_iommu_pagetable_map_prr(mmu, iova, len, prot); + for_each_sgtable_sg(sgt, sg, i) { size_t size = sg->length; phys_addr_t phys = sg_phys(sg); + if (!len) + break; + + if (size <= off) { + off -= size; + continue; + } + + phys += off; + size -= off; + size = min_t(size_t, size, len); + off = 0; + while (size) { size_t pgsize, count, mapped = 0; int ret; @@ -140,6 +206,7 @@ static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, phys += mapped; addr += mapped; size -= mapped; + len -= mapped; if (ret) { msm_iommu_pagetable_unmap(mmu, iova, addr - iova); @@ -162,9 +229,18 @@ static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu) * If this is the last attached pagetable for the parent, * disable TTBR0 in the arm-smmu driver */ - if (atomic_dec_return(&iommu->pagetables) == 0) + mutex_lock(&iommu->init_lock); + if (--iommu->pagetables == 0) { adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, NULL); + if (adreno_smmu->set_prr_bit) { + adreno_smmu->set_prr_bit(adreno_smmu->cookie, false); + __free_page(iommu->prr_page); + iommu->prr_page = NULL; + } + } + mutex_unlock(&iommu->init_lock); + free_io_pgtable_ops(pagetable->pgtbl_ops); kfree(pagetable); } @@ -195,7 +271,175 @@ struct iommu_domain_geometry *msm_iommu_get_geometry(struct msm_mmu *mmu) return &iommu->domain->geometry; } +int +msm_iommu_pagetable_walk(struct msm_mmu *mmu, unsigned long iova, uint64_t ptes[4]) +{ + struct msm_iommu_pagetable *pagetable; + struct arm_lpae_io_pgtable_walk_data wd = {}; + + if (mmu->type != MSM_MMU_IOMMU_PAGETABLE) + return -EINVAL; + + pagetable = to_pagetable(mmu); + + if (!pagetable->pgtbl_ops->pgtable_walk) + return -EINVAL; + + pagetable->pgtbl_ops->pgtable_walk(pagetable->pgtbl_ops, iova, &wd); + + for (int i = 0; i < ARRAY_SIZE(wd.ptes); i++) + ptes[i] = wd.ptes[i]; + + return 0; +} + +static void +msm_iommu_pagetable_prealloc_count(struct msm_mmu *mmu, struct msm_mmu_prealloc *p, + uint64_t iova, size_t len) +{ + u64 pt_count; + + /* + * L1, L2 and L3 page tables. + * + * We could optimize L3 allocation by iterating over the sgt and merging + * 2M contiguous blocks, but it's simpler to over-provision and return + * the pages if they're not used. + * + * The first level descriptor (v8 / v7-lpae page table format) encodes + * 30 bits of address. The second level encodes 29. For the 3rd it is + * 39. + * + * https://developer.arm.com/documentation/ddi0406/c/System-Level-Architecture/Virtual-Memory-System-Architecture--VMSA-/Long-descriptor-translation-table-format/Long-descriptor-translation-table-format-descriptors?lang=en#BEIHEFFB + */ + pt_count = ((ALIGN(iova + len, 1ull << 39) - ALIGN_DOWN(iova, 1ull << 39)) >> 39) + + ((ALIGN(iova + len, 1ull << 30) - ALIGN_DOWN(iova, 1ull << 30)) >> 30) + + ((ALIGN(iova + len, 1ull << 21) - ALIGN_DOWN(iova, 1ull << 21)) >> 21); + + p->count += pt_count; +} + +static struct kmem_cache * +get_pt_cache(struct msm_mmu *mmu) +{ + struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); + return to_msm_iommu(pagetable->parent)->pt_cache; +} + +static int +msm_iommu_pagetable_prealloc_allocate(struct msm_mmu *mmu, struct msm_mmu_prealloc *p) +{ + struct kmem_cache *pt_cache = get_pt_cache(mmu); + int ret; + + p->pages = kvmalloc_array(p->count, sizeof(p->pages), GFP_KERNEL); + if (!p->pages) + return -ENOMEM; + + ret = kmem_cache_alloc_bulk(pt_cache, GFP_KERNEL, p->count, p->pages); + if (ret != p->count) { + kfree(p->pages); + p->pages = NULL; + p->count = ret; + return -ENOMEM; + } + + return 0; +} + +static void +msm_iommu_pagetable_prealloc_cleanup(struct msm_mmu *mmu, struct msm_mmu_prealloc *p) +{ + struct kmem_cache *pt_cache = get_pt_cache(mmu); + uint32_t remaining_pt_count = p->count - p->ptr; + + if (!p->pages) + return; + + if (p->count > 0) + trace_msm_mmu_prealloc_cleanup(p->count, remaining_pt_count); + + kmem_cache_free_bulk(pt_cache, remaining_pt_count, &p->pages[p->ptr]); + kvfree(p->pages); +} + +/** + * alloc_pt() - Custom page table allocator + * @cookie: Cookie passed at page table allocation time. + * @size: Size of the page table. This size should be fixed, + * and determined at creation time based on the granule size. + * @gfp: GFP flags. + * + * We want a custom allocator so we can use a cache for page table + * allocations and amortize the cost of the over-reservation that's + * done to allow asynchronous VM operations. + * + * Return: non-NULL on success, NULL if the allocation failed for any + * reason. + */ +static void * +msm_iommu_pagetable_alloc_pt(void *cookie, size_t size, gfp_t gfp) +{ + struct msm_iommu_pagetable *pagetable = cookie; + struct msm_mmu_prealloc *p = pagetable->base.prealloc; + void *page; + + /* Allocation of the root page table happening during init. */ + if (unlikely(!pagetable->root_page_table)) { + struct page *p; + + p = alloc_pages_node(dev_to_node(pagetable->iommu_dev), + gfp | __GFP_ZERO, get_order(size)); + page = p ? page_address(p) : NULL; + pagetable->root_page_table = page; + return page; + } + + if (WARN_ON(!p) || WARN_ON(p->ptr >= p->count)) + return NULL; + + page = p->pages[p->ptr++]; + memset(page, 0, size); + + /* + * Page table entries don't use virtual addresses, which trips out + * kmemleak. kmemleak_alloc_phys() might work, but physical addresses + * are mixed with other fields, and I fear kmemleak won't detect that + * either. + * + * Let's just ignore memory passed to the page-table driver for now. + */ + kmemleak_ignore(page); + + return page; +} + + +/** + * free_pt() - Custom page table free function + * @cookie: Cookie passed at page table allocation time. + * @data: Page table to free. + * @size: Size of the page table. This size should be fixed, + * and determined at creation time based on the granule size. + */ +static void +msm_iommu_pagetable_free_pt(void *cookie, void *data, size_t size) +{ + struct msm_iommu_pagetable *pagetable = cookie; + + if (unlikely(pagetable->root_page_table == data)) { + free_pages((unsigned long)data, get_order(size)); + pagetable->root_page_table = NULL; + return; + } + + kmem_cache_free(get_pt_cache(&pagetable->base), data); +} + static const struct msm_mmu_funcs pagetable_funcs = { + .prealloc_count = msm_iommu_pagetable_prealloc_count, + .prealloc_allocate = msm_iommu_pagetable_prealloc_allocate, + .prealloc_cleanup = msm_iommu_pagetable_prealloc_cleanup, .map = msm_iommu_pagetable_map, .unmap = msm_iommu_pagetable_unmap, .destroy = msm_iommu_pagetable_destroy, @@ -243,10 +487,21 @@ static const struct iommu_flush_ops tlb_ops = { .tlb_add_page = msm_iommu_tlb_add_page, }; -static int msm_fault_handler(struct iommu_domain *domain, struct device *dev, +static int msm_gpu_fault_handler(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags, void *arg); -struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent) +static size_t get_tblsz(const struct io_pgtable_cfg *cfg) +{ + int pg_shift, bits_per_level; + + pg_shift = __ffs(cfg->pgsize_bitmap); + /* arm_lpae_iopte is u64: */ + bits_per_level = pg_shift - ilog2(sizeof(u64)); + + return sizeof(u64) << bits_per_level; +} + +struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_managed) { struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(parent->dev); struct msm_iommu *iommu = to_msm_iommu(parent); @@ -280,6 +535,36 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent) ttbr0_cfg.quirks &= ~IO_PGTABLE_QUIRK_ARM_TTBR1; ttbr0_cfg.tlb = &tlb_ops; + if (!kernel_managed) { + ttbr0_cfg.quirks |= IO_PGTABLE_QUIRK_NO_WARN; + + /* + * With userspace managed VM (aka VM_BIND), we need to pre- + * allocate pages ahead of time for map/unmap operations, + * handing them to io-pgtable via custom alloc/free ops as + * needed: + */ + ttbr0_cfg.alloc = msm_iommu_pagetable_alloc_pt; + ttbr0_cfg.free = msm_iommu_pagetable_free_pt; + + /* + * Restrict to single page granules. Otherwise we may run + * into a situation where userspace wants to unmap/remap + * only a part of a larger block mapping, which is not + * possible without unmapping the entire block. Which in + * turn could cause faults if the GPU is accessing other + * parts of the block mapping. + * + * Note that prior to commit 33729a5fc0ca ("iommu/io-pgtable-arm: + * Remove split on unmap behavior)" this was handled in + * io-pgtable-arm. But this apparently does not work + * correctly on SMMUv3. + */ + WARN_ON(!(ttbr0_cfg.pgsize_bitmap & PAGE_SIZE)); + ttbr0_cfg.pgsize_bitmap = PAGE_SIZE; + } + + pagetable->iommu_dev = ttbr1_cfg->iommu_dev; pagetable->pgtbl_ops = alloc_io_pgtable_ops(ARM_64_LPAE_S1, &ttbr0_cfg, pagetable); @@ -292,19 +577,41 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent) * If this is the first pagetable that we've allocated, send it back to * the arm-smmu driver as a trigger to set up TTBR0 */ - if (atomic_inc_return(&iommu->pagetables) == 1) { + mutex_lock(&iommu->init_lock); + if (iommu->pagetables++ == 0) { ret = adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, &ttbr0_cfg); if (ret) { + iommu->pagetables--; + mutex_unlock(&iommu->init_lock); free_io_pgtable_ops(pagetable->pgtbl_ops); kfree(pagetable); return ERR_PTR(ret); } + + BUG_ON(iommu->prr_page); + if (adreno_smmu->set_prr_bit) { + /* + * We need a zero'd page for two reasons: + * + * 1) Reserve a known physical address to use when + * mapping NULL / sparsely resident regions + * 2) Read back zero + * + * It appears the hw drops writes to the PRR region + * on the floor, but reads actually return whatever + * is in the PRR page. + */ + iommu->prr_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + adreno_smmu->set_prr_addr(adreno_smmu->cookie, + page_to_phys(iommu->prr_page)); + adreno_smmu->set_prr_bit(adreno_smmu->cookie, true); + } } + mutex_unlock(&iommu->init_lock); /* 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; @@ -319,11 +626,10 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent) return &pagetable->base; } -static int msm_fault_handler(struct iommu_domain *domain, struct device *dev, +static int msm_gpu_fault_handler(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags, void *arg) { struct msm_iommu *iommu = arg; - struct msm_mmu *mmu = &iommu->base; struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(iommu->base.dev); struct adreno_smmu_fault_info info, *ptr = NULL; @@ -337,18 +643,26 @@ static int msm_fault_handler(struct iommu_domain *domain, struct device *dev, pr_warn_ratelimited("*** fault: iova=%16lx, flags=%d\n", iova, flags); - if (mmu->funcs->resume_translation) - mmu->funcs->resume_translation(mmu); - return 0; } -static void msm_iommu_resume_translation(struct msm_mmu *mmu) +static int msm_disp_fault_handler(struct iommu_domain *domain, struct device *dev, + unsigned long iova, int flags, void *arg) +{ + struct msm_iommu *iommu = arg; + + if (iommu->base.handler) + return iommu->base.handler(iommu->base.arg, iova, flags, NULL); + + return -ENOSYS; +} + +static void msm_iommu_set_stall(struct msm_mmu *mmu, bool enable) { struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(mmu->dev); - if (adreno_smmu->resume_translation) - adreno_smmu->resume_translation(adreno_smmu->cookie, true); + if (adreno_smmu->set_stall) + adreno_smmu->set_stall(adreno_smmu->cookie, enable); } static void msm_iommu_detach(struct msm_mmu *mmu) @@ -359,11 +673,14 @@ static void msm_iommu_detach(struct msm_mmu *mmu) } static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, - struct sg_table *sgt, size_t len, int prot) + struct sg_table *sgt, size_t off, size_t len, + int prot) { struct msm_iommu *iommu = to_msm_iommu(mmu); size_t ret; + WARN_ON(off != 0); + /* The arm-smmu driver expects the addresses to be sign extended */ if (iova & BIT_ULL(48)) iova |= GENMASK_ULL(63, 49); @@ -390,6 +707,7 @@ static void msm_iommu_destroy(struct msm_mmu *mmu) { struct msm_iommu *iommu = to_msm_iommu(mmu); iommu_domain_free(iommu->domain); + kmem_cache_destroy(iommu->pt_cache); kfree(iommu); } @@ -398,7 +716,7 @@ static const struct msm_mmu_funcs funcs = { .map = msm_iommu_map, .unmap = msm_iommu_unmap, .destroy = msm_iommu_destroy, - .resume_translation = msm_iommu_resume_translation, + .set_stall = msm_iommu_set_stall, }; struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks) @@ -408,7 +726,7 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks) int ret; if (!device_iommu_mapped(dev)) - return NULL; + return ERR_PTR(-ENODEV); domain = iommu_paging_domain_alloc(dev); if (IS_ERR(domain)) @@ -425,7 +743,7 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks) iommu->domain = domain; msm_mmu_init(&iommu->base, dev, &funcs, MSM_MMU_IOMMU); - atomic_set(&iommu->pagetables, 0); + mutex_init(&iommu->init_lock); ret = iommu_attach_device(iommu->domain, dev); if (ret) { @@ -437,6 +755,21 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks) return &iommu->base; } +struct msm_mmu *msm_iommu_disp_new(struct device *dev, unsigned long quirks) +{ + struct msm_iommu *iommu; + struct msm_mmu *mmu; + + mmu = msm_iommu_new(dev, quirks); + if (IS_ERR(mmu)) + return mmu; + + iommu = to_msm_iommu(mmu); + iommu_set_fault_handler(iommu->domain, msm_disp_fault_handler, iommu); + + return mmu; +} + struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsigned long quirks) { struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(dev); @@ -444,11 +777,19 @@ struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsig struct msm_mmu *mmu; mmu = msm_iommu_new(dev, quirks); - if (IS_ERR_OR_NULL(mmu)) + if (IS_ERR(mmu)) return mmu; iommu = to_msm_iommu(mmu); - iommu_set_fault_handler(iommu->domain, msm_fault_handler, iommu); + if (adreno_smmu->cookie) { + const struct io_pgtable_cfg *cfg = + adreno_smmu->get_ttbr1_cfg(adreno_smmu->cookie); + size_t tblsz = get_tblsz(cfg); + + iommu->pt_cache = + kmem_cache_create("msm-mmu-pt", tblsz, tblsz, 0, NULL); + } + iommu_set_fault_handler(iommu->domain, msm_gpu_fault_handler, iommu); /* Enable stall on iommu fault: */ if (adreno_smmu->set_stall) diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c index f3326d09bdbc..6e5e94f5c9a7 100644 --- a/drivers/gpu/drm/msm/msm_kms.c +++ b/drivers/gpu/drm/msm/msm_kms.c @@ -13,6 +13,7 @@ #include <drm/drm_drv.h> #include <drm/drm_mode_config.h> #include <drm/drm_vblank.h> +#include <drm/clients/drm_client_setup.h> #include "disp/msm_disp_snapshot.h" #include "msm_drv.h" @@ -137,7 +138,7 @@ static int vblank_ctrl_queue_work(struct msm_drm_private *priv, vbl_work->enable = enable; vbl_work->priv = priv; - queue_work(priv->wq, &vbl_work->work); + queue_work(priv->kms->wq, &vbl_work->work); return 0; } @@ -164,12 +165,25 @@ void msm_crtc_disable_vblank(struct drm_crtc *crtc) vblank_ctrl_queue_work(priv, crtc, false); } -struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev) +static int msm_kms_fault_handler(void *arg, unsigned long iova, int flags, void *data) { - struct msm_gem_address_space *aspace; + struct msm_kms *kms = arg; + + if (atomic_read(&kms->fault_snapshot_capture) == 0) { + msm_disp_snapshot_state(kms->dev); + atomic_inc(&kms->fault_snapshot_capture); + } + + return -ENOSYS; +} + +struct drm_gpuvm *msm_kms_init_vm(struct drm_device *dev, struct device *mdss_dev) +{ + struct drm_gpuvm *vm; struct msm_mmu *mmu; struct device *mdp_dev = dev->dev; - struct device *mdss_dev = mdp_dev->parent; + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; struct device *iommu_dev; /* @@ -178,26 +192,37 @@ struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev) */ if (device_iommu_mapped(mdp_dev)) iommu_dev = mdp_dev; - else + else if (mdss_dev && device_iommu_mapped(mdss_dev)) iommu_dev = mdss_dev; + else { + drm_info(dev, "no IOMMU, bailing out\n"); + return ERR_PTR(-ENODEV); + } - mmu = msm_iommu_new(iommu_dev, 0); + mmu = msm_iommu_disp_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); + vm = msm_gem_vm_create(dev, mmu, "mdp_kms", + 0x1000, 0x100000000 - 0x1000, true); + if (IS_ERR(vm)) { + dev_err(mdp_dev, "vm create, error %pe\n", vm); mmu->funcs->destroy(mmu); + return vm; } - return aspace; + msm_mmu_set_fault_handler(to_msm_vm(vm)->mmu, kms, msm_kms_fault_handler); + + return vm; +} + +void msm_drm_kms_unregister(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; + + drm_atomic_helper_shutdown(ddev); } void msm_drm_kms_uninit(struct device *dev) @@ -210,10 +235,17 @@ void msm_drm_kms_uninit(struct device *dev) BUG_ON(!kms); + /* We must cancel and cleanup any pending vblank enable/disable + * work before msm_irq_uninstall() to avoid work re-enabling an + * irq after uninstall has disabled it. + */ + + flush_workqueue(kms->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); + for (i = 0; i < MAX_CRTCS; i++) { + if (kms->event_thread[i].worker) + kthread_destroy_worker(kms->event_thread[i].worker); } drm_kms_helper_poll_fini(ddev); @@ -241,11 +273,16 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) if (ret) return ret; + ret = msm_disp_snapshot_init(ddev); + if (ret) { + DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); + return ret; + } + ret = priv->kms_init(ddev); if (ret) { DRM_DEV_ERROR(dev, "failed to load kms\n"); - priv->kms = NULL; - return ret; + goto err_msm_uninit; } /* Enable normalization of plane zpos */ @@ -267,9 +304,9 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) struct msm_drm_thread *ev_thread; /* initialize event thread */ - ev_thread = &priv->event_thread[drm_crtc_index(crtc)]; + ev_thread = &kms->event_thread[drm_crtc_index(crtc)]; ev_thread->dev = ddev; - ev_thread->worker = kthread_create_worker(0, "crtc_event:%d", crtc->base.id); + ev_thread->worker = kthread_run_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"); @@ -280,7 +317,7 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) sched_set_fifo(ev_thread->worker->task); } - ret = drm_vblank_init(ddev, priv->num_crtcs); + ret = drm_vblank_init(ddev, ddev->mode_config.num_crtc); if (ret < 0) { DRM_DEV_ERROR(dev, "failed to initialize vblank\n"); goto err_msm_uninit; @@ -294,10 +331,6 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) 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; @@ -343,3 +376,13 @@ void msm_kms_shutdown(struct platform_device *pdev) if (drm && drm->registered && priv->kms) drm_atomic_helper_shutdown(drm); } + +void msm_drm_kms_post_init(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; + + drm_kms_helper_poll_init(ddev); + drm_client_setup(ddev, NULL); +} diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index e60162744c66..8a7be7b854de 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -13,6 +13,8 @@ #include "msm_drv.h" +#ifdef CONFIG_DRM_MSM_KMS + #define MAX_PLANE 4 /* As there are different display controller blocks depending on the @@ -60,6 +62,13 @@ struct msm_kms_funcs { void (*disable_commit)(struct msm_kms *kms); /** + * @check_mode_changed: + * + * Verify if the commit requires a full modeset on one of CRTCs. + */ + int (*check_mode_changed)(struct msm_kms *kms, struct drm_atomic_state *state); + + /** * Prepare for atomic commit. This is called after any previous * (async or otherwise) commit has completed. */ @@ -120,16 +129,31 @@ struct msm_pending_timer { unsigned crtc_idx; }; +/* Commit/Event thread specific structure */ +struct msm_drm_thread { + struct drm_device *dev; + struct kthread_worker *worker; +}; + struct msm_kms { const struct msm_kms_funcs *funcs; struct drm_device *dev; + struct hdmi *hdmi; + + struct msm_dsi *dsi[MSM_DSI_CONTROLLER_COUNT]; + + struct msm_dp *dp[MSM_DP_CONTROLLER_COUNT]; + /* irq number to be passed on to msm_irq_install */ int irq; bool irq_requested; + /* rate limit the snapshot capture to once per attach */ + atomic_t fault_snapshot_capture; + /* mapper-id used to request GEM buffer mapped for scanout: */ - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; /* disp snapshot support */ struct kthread_worker *dump_worker; @@ -143,6 +167,9 @@ struct msm_kms { struct mutex commit_lock[MAX_CRTCS]; unsigned pending_crtc_mask; struct msm_pending_timer pending_timers[MAX_CRTCS]; + + struct workqueue_struct *wq; + struct msm_drm_thread event_thread[MAX_CRTCS]; }; static inline int msm_kms_init(struct msm_kms *kms, @@ -155,6 +182,10 @@ static inline int msm_kms_init(struct msm_kms *kms, kms->funcs = funcs; + kms->wq = alloc_ordered_workqueue("msm", 0); + if (!kms->wq) + return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++) { ret = msm_atomic_init_pending_timer(&kms->pending_timers[i], kms, i); if (ret) { @@ -171,6 +202,8 @@ static inline void msm_kms_destroy(struct msm_kms *kms) for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++) msm_atomic_destroy_pending_timer(&kms->pending_timers[i]); + + destroy_workqueue(kms->wq); } #define for_each_crtc_mask(dev, crtc, crtc_mask) \ @@ -182,6 +215,29 @@ static inline void msm_kms_destroy(struct msm_kms *kms) 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_post_init(struct device *dev); +void msm_drm_kms_unregister(struct device *dev); void msm_drm_kms_uninit(struct device *dev); +#else /* ! CONFIG_DRM_MSM_KMS */ + +static inline int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) +{ + return -ENODEV; +} + +static inline void msm_drm_kms_post_init(struct device *dev) +{ +} + +static inline void msm_drm_kms_unregister(struct device *dev) +{ +} + +static inline void msm_drm_kms_uninit(struct device *dev) +{ +} + +#endif + #endif /* __MSM_KMS_H__ */ diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index b7bd899ead44..bf9a33e925ac 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -16,14 +16,17 @@ #include <linux/pm_runtime.h> #include <linux/reset.h> -#include "msm_mdss.h" +#include <linux/soc/qcom/ubwc.h> + #include "msm_kms.h" #include <generated/mdss.xml.h> #define MIN_IB_BW 400000000UL /* Min ib vote 400MB */ -#define DEFAULT_REG_BW 153600 /* Used in mdss fbdev driver */ +struct msm_mdss_data { + u32 reg_bus_bw; +}; struct msm_mdss { struct device *dev; @@ -36,7 +39,8 @@ struct msm_mdss { unsigned long enabled_mask; struct irq_domain *domain; } irq_controller; - const struct msm_mdss_data *mdss_data; + const struct qcom_ubwc_cfg_data *mdss_data; + u32 reg_bus_bw; struct icc_path *mdp_path[2]; u32 num_mdp_paths; struct icc_path *reg_bus_path; @@ -150,8 +154,7 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss) dev = msm_mdss->dev; - domain = irq_domain_add_linear(dev->of_node, 32, - &msm_mdss_irqdomain_ops, msm_mdss); + domain = irq_domain_create_linear(dev_fwnode(dev), 32, &msm_mdss_irqdomain_ops, msm_mdss); if (!domain) { dev_err(dev, "failed to add irq_domain\n"); return -EINVAL; @@ -165,34 +168,48 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss) static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss) { - const struct msm_mdss_data *data = msm_mdss->mdss_data; + const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data; + u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) | + MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit - 13); + + if (data->ubwc_bank_spread) + value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD; + + if (data->ubwc_enc_version == UBWC_1_0) + value |= MDSS_UBWC_STATIC_UBWC_MIN_ACC_LEN(1); - writel_relaxed(data->ubwc_static, msm_mdss->mmio + REG_MDSS_UBWC_STATIC); + writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC); } static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss) { - const struct msm_mdss_data *data = msm_mdss->mdss_data; - u32 value = (data->ubwc_swizzle & 0x1) | - (data->highest_bank_bit & 0x3) << 4 | - (data->macrotile_mode & 0x1) << 12; + const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data; + u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle & 0x1) | + MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit - 13); + + if (data->macrotile_mode) + value |= MDSS_UBWC_STATIC_MACROTILE_MODE; if (data->ubwc_enc_version == UBWC_3_0) - value |= BIT(10); + value |= MDSS_UBWC_STATIC_UBWC_AMSBC; if (data->ubwc_enc_version == UBWC_1_0) - value |= BIT(8); + value |= MDSS_UBWC_STATIC_UBWC_MIN_ACC_LEN(1); writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC); } static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss) { - const struct msm_mdss_data *data = msm_mdss->mdss_data; - u32 value = (data->ubwc_swizzle & 0x7) | - (data->ubwc_static & 0x1) << 3 | - (data->highest_bank_bit & 0x7) << 4 | - (data->macrotile_mode & 0x1) << 12; + const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data; + u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) | + MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit - 13); + + if (data->ubwc_bank_spread) + value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD; + + if (data->macrotile_mode) + value |= MDSS_UBWC_STATIC_MACROTILE_MODE; writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC); @@ -208,67 +225,22 @@ static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss) } } -#define MDSS_HW_MAJ_MIN \ - (MDSS_HW_VERSION_MAJOR__MASK | MDSS_HW_VERSION_MINOR__MASK) - -#define MDSS_HW_MSM8996 0x1007 -#define MDSS_HW_MSM8937 0x100e -#define MDSS_HW_MSM8953 0x1010 -#define MDSS_HW_MSM8998 0x3000 -#define MDSS_HW_SDM660 0x3002 -#define MDSS_HW_SDM630 0x3003 - -/* - * MDP5 platforms use generic qcom,mdp5 compat string, so we have to generate this data - */ -static const struct msm_mdss_data *msm_mdss_generate_mdp5_mdss_data(struct msm_mdss *mdss) -{ - struct msm_mdss_data *data; - u32 hw_rev; - - data = devm_kzalloc(mdss->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return NULL; - - hw_rev = readl_relaxed(mdss->mmio + REG_MDSS_HW_VERSION); - hw_rev = FIELD_GET(MDSS_HW_MAJ_MIN, hw_rev); - - if (hw_rev == MDSS_HW_MSM8996 || - hw_rev == MDSS_HW_MSM8937 || - hw_rev == MDSS_HW_MSM8953 || - hw_rev == MDSS_HW_MSM8998 || - hw_rev == MDSS_HW_SDM660 || - hw_rev == MDSS_HW_SDM630) { - data->ubwc_dec_version = UBWC_1_0; - data->ubwc_enc_version = UBWC_1_0; - } - - if (hw_rev == MDSS_HW_MSM8996 || - hw_rev == MDSS_HW_MSM8998) - data->highest_bank_bit = 2; - else - data->highest_bank_bit = 1; - - return data; -} - -const struct msm_mdss_data *msm_mdss_get_mdss_data(struct device *dev) +static void msm_mdss_setup_ubwc_dec_50(struct msm_mdss *msm_mdss) { - struct msm_mdss *mdss; + const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data; + u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) | + MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit); - if (!dev) - return ERR_PTR(-EINVAL); + if (data->ubwc_bank_spread) + value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD; - mdss = dev_get_drvdata(dev); + if (data->macrotile_mode) + value |= MDSS_UBWC_STATIC_MACROTILE_MODE; - /* - * We could not do it at the probe time, since hw revision register was - * not readable. Fill data structure now for the MDP5 platforms. - */ - if (!mdss->mdss_data && mdss->is_mdp5) - mdss->mdss_data = msm_mdss_generate_mdp5_mdss_data(mdss); + writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC); - return mdss->mdss_data; + writel_relaxed(4, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2); + writel_relaxed(1, msm_mdss->mmio + REG_MDSS_UBWC_PREDICTION_MODE); } static int msm_mdss_enable(struct msm_mdss *msm_mdss) @@ -283,12 +255,8 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss) for (i = 0; i < msm_mdss->num_mdp_paths; i++) icc_set_bw(msm_mdss->mdp_path[i], 0, Bps_to_icc(MIN_IB_BW)); - if (msm_mdss->mdss_data && msm_mdss->mdss_data->reg_bus_bw) - icc_set_bw(msm_mdss->reg_bus_path, 0, - msm_mdss->mdss_data->reg_bus_bw); - else - icc_set_bw(msm_mdss->reg_bus_path, 0, - DEFAULT_REG_BW); + icc_set_bw(msm_mdss->reg_bus_path, 0, + msm_mdss->reg_bus_bw); ret = clk_bulk_prepare_enable(msm_mdss->num_clocks, msm_mdss->clocks); if (ret) { @@ -325,6 +293,9 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss) case UBWC_4_3: msm_mdss_setup_ubwc_dec_40(msm_mdss); break; + case UBWC_5_0: + msm_mdss_setup_ubwc_dec_50(msm_mdss); + break; default: dev_err(msm_mdss->dev, "Unsupported UBWC decoder version %x\n", msm_mdss->mdss_data->ubwc_dec_version); @@ -424,6 +395,7 @@ static int mdp5_mdss_parse_clock(struct platform_device *pdev, struct clk_bulk_d static struct msm_mdss *msm_mdss_init(struct platform_device *pdev, bool is_mdp5) { + const struct msm_mdss_data *mdss_data; struct msm_mdss *msm_mdss; int ret; int irq; @@ -436,13 +408,21 @@ static struct msm_mdss *msm_mdss_init(struct platform_device *pdev, bool is_mdp5 if (!msm_mdss) return ERR_PTR(-ENOMEM); - msm_mdss->mdss_data = of_device_get_match_data(&pdev->dev); + msm_mdss->mdss_data = qcom_ubwc_config_get_data(); + if (IS_ERR(msm_mdss->mdss_data)) + return ERR_CAST(msm_mdss->mdss_data); + + mdss_data = of_device_get_match_data(&pdev->dev); + if (!mdss_data) + return ERR_PTR(-EINVAL); + + msm_mdss->reg_bus_bw = mdss_data->reg_bus_bw; msm_mdss->mmio = devm_platform_ioremap_resource_byname(pdev, is_mdp5 ? "mdss_phys" : "mdss"); if (IS_ERR(msm_mdss->mmio)) return ERR_CAST(msm_mdss->mmio); - dev_dbg(&pdev->dev, "mapped mdss address space @%pK\n", msm_mdss->mmio); + dev_dbg(&pdev->dev, "mapped mdss address space @%p\n", msm_mdss->mmio); ret = msm_mdss_parse_data_bus_icc_path(&pdev->dev, msm_mdss); if (ret) @@ -555,192 +535,58 @@ static void mdss_remove(struct platform_device *pdev) msm_mdss_destroy(mdss); } -static const struct msm_mdss_data msm8998_data = { - .ubwc_enc_version = UBWC_1_0, - .ubwc_dec_version = UBWC_1_0, - .highest_bank_bit = 2, - .reg_bus_bw = 76800, -}; - -static const struct msm_mdss_data qcm2290_data = { - /* no UBWC */ - .highest_bank_bit = 0x2, - .reg_bus_bw = 76800, -}; - -static const struct msm_mdss_data sa8775p_data = { - .ubwc_enc_version = UBWC_4_0, - .ubwc_dec_version = UBWC_4_0, - .ubwc_swizzle = 4, - .ubwc_static = 1, - .highest_bank_bit = 0, - .macrotile_mode = 1, - .reg_bus_bw = 74000, -}; - -static const struct msm_mdss_data sc7180_data = { - .ubwc_enc_version = UBWC_2_0, - .ubwc_dec_version = UBWC_2_0, - .ubwc_static = 0x1e, - .highest_bank_bit = 0x1, - .reg_bus_bw = 76800, +static const struct msm_mdss_data data_57k = { + .reg_bus_bw = 57000, }; -static const struct msm_mdss_data sc7280_data = { - .ubwc_enc_version = UBWC_3_0, - .ubwc_dec_version = UBWC_4_0, - .ubwc_swizzle = 6, - .ubwc_static = 1, - .highest_bank_bit = 1, - .macrotile_mode = 1, +static const struct msm_mdss_data data_74k = { .reg_bus_bw = 74000, }; -static const struct msm_mdss_data sc8180x_data = { - .ubwc_enc_version = UBWC_3_0, - .ubwc_dec_version = UBWC_3_0, - .highest_bank_bit = 3, - .macrotile_mode = 1, +static const struct msm_mdss_data data_76k8 = { .reg_bus_bw = 76800, }; -static const struct msm_mdss_data sc8280xp_data = { - .ubwc_enc_version = UBWC_4_0, - .ubwc_dec_version = UBWC_4_0, - .ubwc_swizzle = 6, - .ubwc_static = 1, - .highest_bank_bit = 3, - .macrotile_mode = 1, - .reg_bus_bw = 76800, -}; - -static const struct msm_mdss_data sdm670_data = { - .ubwc_enc_version = UBWC_2_0, - .ubwc_dec_version = UBWC_2_0, - .highest_bank_bit = 1, - .reg_bus_bw = 76800, -}; - -static const struct msm_mdss_data sdm845_data = { - .ubwc_enc_version = UBWC_2_0, - .ubwc_dec_version = UBWC_2_0, - .highest_bank_bit = 2, - .reg_bus_bw = 76800, -}; - -static const struct msm_mdss_data sm6350_data = { - .ubwc_enc_version = UBWC_2_0, - .ubwc_dec_version = UBWC_2_0, - .ubwc_swizzle = 6, - .ubwc_static = 0x1e, - .highest_bank_bit = 1, - .reg_bus_bw = 76800, -}; - -static const struct msm_mdss_data sm7150_data = { - .ubwc_enc_version = UBWC_2_0, - .ubwc_dec_version = UBWC_2_0, - .highest_bank_bit = 1, - .reg_bus_bw = 76800, -}; - -static const struct msm_mdss_data sm8150_data = { - .ubwc_enc_version = UBWC_3_0, - .ubwc_dec_version = UBWC_3_0, - .highest_bank_bit = 2, - .reg_bus_bw = 76800, -}; - -static const struct msm_mdss_data sm6115_data = { - .ubwc_enc_version = UBWC_1_0, - .ubwc_dec_version = UBWC_2_0, - .ubwc_swizzle = 7, - .ubwc_static = 0x11f, - .highest_bank_bit = 0x1, - .reg_bus_bw = 76800, -}; - -static const struct msm_mdss_data sm6125_data = { - .ubwc_enc_version = UBWC_1_0, - .ubwc_dec_version = UBWC_3_0, - .ubwc_swizzle = 1, - .highest_bank_bit = 1, -}; - -static const struct msm_mdss_data sm8250_data = { - .ubwc_enc_version = UBWC_4_0, - .ubwc_dec_version = UBWC_4_0, - .ubwc_swizzle = 6, - .ubwc_static = 1, - /* TODO: highest_bank_bit = 2 for LP_DDR4 */ - .highest_bank_bit = 3, - .macrotile_mode = 1, - .reg_bus_bw = 76800, -}; - -static const struct msm_mdss_data sm8350_data = { - .ubwc_enc_version = UBWC_4_0, - .ubwc_dec_version = UBWC_4_0, - .ubwc_swizzle = 6, - .ubwc_static = 1, - /* TODO: highest_bank_bit = 2 for LP_DDR4 */ - .highest_bank_bit = 3, - .macrotile_mode = 1, - .reg_bus_bw = 74000, -}; - -static const struct msm_mdss_data sm8550_data = { - .ubwc_enc_version = UBWC_4_0, - .ubwc_dec_version = UBWC_4_3, - .ubwc_swizzle = 6, - .ubwc_static = 1, - /* TODO: highest_bank_bit = 2 for LP_DDR4 */ - .highest_bank_bit = 3, - .macrotile_mode = 1, - .reg_bus_bw = 57000, -}; - -static const struct msm_mdss_data x1e80100_data = { - .ubwc_enc_version = UBWC_4_0, - .ubwc_dec_version = UBWC_4_3, - .ubwc_swizzle = 6, - .ubwc_static = 1, - /* TODO: highest_bank_bit = 2 for LP_DDR4 */ - .highest_bank_bit = 3, - .macrotile_mode = 1, - /* TODO: Add reg_bus_bw with real value */ +static const struct msm_mdss_data data_153k6 = { + .reg_bus_bw = 153600, }; static const struct of_device_id mdss_dt_match[] = { - { .compatible = "qcom,mdss" }, - { .compatible = "qcom,msm8998-mdss", .data = &msm8998_data }, - { .compatible = "qcom,qcm2290-mdss", .data = &qcm2290_data }, - { .compatible = "qcom,sa8775p-mdss", .data = &sa8775p_data }, - { .compatible = "qcom,sdm670-mdss", .data = &sdm670_data }, - { .compatible = "qcom,sdm845-mdss", .data = &sdm845_data }, - { .compatible = "qcom,sc7180-mdss", .data = &sc7180_data }, - { .compatible = "qcom,sc7280-mdss", .data = &sc7280_data }, - { .compatible = "qcom,sc8180x-mdss", .data = &sc8180x_data }, - { .compatible = "qcom,sc8280xp-mdss", .data = &sc8280xp_data }, - { .compatible = "qcom,sm6115-mdss", .data = &sm6115_data }, - { .compatible = "qcom,sm6125-mdss", .data = &sm6125_data }, - { .compatible = "qcom,sm6350-mdss", .data = &sm6350_data }, - { .compatible = "qcom,sm6375-mdss", .data = &sm6350_data }, - { .compatible = "qcom,sm7150-mdss", .data = &sm7150_data }, - { .compatible = "qcom,sm8150-mdss", .data = &sm8150_data }, - { .compatible = "qcom,sm8250-mdss", .data = &sm8250_data }, - { .compatible = "qcom,sm8350-mdss", .data = &sm8350_data }, - { .compatible = "qcom,sm8450-mdss", .data = &sm8350_data }, - { .compatible = "qcom,sm8550-mdss", .data = &sm8550_data }, - { .compatible = "qcom,sm8650-mdss", .data = &sm8550_data}, - { .compatible = "qcom,x1e80100-mdss", .data = &x1e80100_data}, + { .compatible = "qcom,mdss", .data = &data_153k6 }, + { .compatible = "qcom,glymur-mdss", .data = &data_57k }, + { .compatible = "qcom,msm8998-mdss", .data = &data_76k8 }, + { .compatible = "qcom,qcm2290-mdss", .data = &data_76k8 }, + { .compatible = "qcom,qcs8300-mdss", .data = &data_74k }, + { .compatible = "qcom,sa8775p-mdss", .data = &data_74k }, + { .compatible = "qcom,sar2130p-mdss", .data = &data_74k }, + { .compatible = "qcom,sdm670-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sdm845-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sc7180-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sc7280-mdss", .data = &data_74k }, + { .compatible = "qcom,sc8180x-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sc8280xp-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sm6115-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sm6125-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sm6150-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sm6350-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sm6375-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sm7150-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sm8150-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sm8250-mdss", .data = &data_76k8 }, + { .compatible = "qcom,sm8350-mdss", .data = &data_74k }, + { .compatible = "qcom,sm8450-mdss", .data = &data_74k }, + { .compatible = "qcom,sm8550-mdss", .data = &data_57k }, + { .compatible = "qcom,sm8650-mdss", .data = &data_57k }, + { .compatible = "qcom,sm8750-mdss", .data = &data_57k }, + /* TODO: x1e8: Add reg_bus_bw with real value */ + { .compatible = "qcom,x1e80100-mdss", .data = &data_153k6 }, {} }; MODULE_DEVICE_TABLE(of, mdss_dt_match); static struct platform_driver mdss_platform_driver = { .probe = mdss_probe, - .remove_new = mdss_remove, + .remove = mdss_remove, .driver = { .name = "msm-mdss", .of_match_table = mdss_dt_match, diff --git a/drivers/gpu/drm/msm/msm_mdss.h b/drivers/gpu/drm/msm/msm_mdss.h deleted file mode 100644 index 3afef4b1786d..000000000000 --- a/drivers/gpu/drm/msm/msm_mdss.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2018, The Linux Foundation - */ - -#ifndef __MSM_MDSS_H__ -#define __MSM_MDSS_H__ - -struct msm_mdss_data { - u32 ubwc_enc_version; - /* can be read from register 0x58 */ - u32 ubwc_dec_version; - u32 ubwc_swizzle; - u32 ubwc_static; - u32 highest_bank_bit; - u32 macrotile_mode; - u32 reg_bus_bw; -}; - -#define UBWC_1_0 0x10000000 -#define UBWC_2_0 0x20000000 -#define UBWC_3_0 0x30000000 -#define UBWC_4_0 0x40000000 -#define UBWC_4_3 0x40030000 - -const struct msm_mdss_data *msm_mdss_get_mdss_data(struct device *dev); - -#endif /* __MSM_MDSS_H__ */ diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h index 88af4f490881..8915662fbd4d 100644 --- a/drivers/gpu/drm/msm/msm_mmu.h +++ b/drivers/gpu/drm/msm/msm_mmu.h @@ -9,13 +9,21 @@ #include <linux/iommu.h> +struct msm_mmu_prealloc; +struct msm_mmu; +struct msm_gpu; + struct msm_mmu_funcs { void (*detach)(struct msm_mmu *mmu); + void (*prealloc_count)(struct msm_mmu *mmu, struct msm_mmu_prealloc *p, + uint64_t iova, size_t len); + int (*prealloc_allocate)(struct msm_mmu *mmu, struct msm_mmu_prealloc *p); + void (*prealloc_cleanup)(struct msm_mmu *mmu, struct msm_mmu_prealloc *p); int (*map)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt, - size_t len, int prot); + size_t off, size_t len, int prot); int (*unmap)(struct msm_mmu *mmu, uint64_t iova, size_t len); void (*destroy)(struct msm_mmu *mmu); - void (*resume_translation)(struct msm_mmu *mmu); + void (*set_stall)(struct msm_mmu *mmu, bool enable); }; enum msm_mmu_type { @@ -24,12 +32,38 @@ enum msm_mmu_type { MSM_MMU_IOMMU_PAGETABLE, }; +/** + * struct msm_mmu_prealloc - Tracking for pre-allocated pages for MMU updates. + */ +struct msm_mmu_prealloc { + /** @count: Number of pages reserved. */ + uint32_t count; + /** @ptr: Index of first unused page in @pages */ + uint32_t ptr; + /** + * @pages: Array of pages preallocated for MMU table updates. + * + * After a VM operation, there might be free pages remaining in this + * array (since the amount allocated is a worst-case). These are + * returned to the pt_cache at mmu->prealloc_cleanup(). + */ + void **pages; +}; + struct msm_mmu { const struct msm_mmu_funcs *funcs; struct device *dev; int (*handler)(void *arg, unsigned long iova, int flags, void *data); void *arg; enum msm_mmu_type type; + + /** + * @prealloc: pre-allocated pages for pgtable + * + * Set while a VM_BIND job is running, serialized under + * msm_gem_vm::mmu_lock. + */ + struct msm_mmu_prealloc *prealloc; }; static inline void msm_mmu_init(struct msm_mmu *mmu, struct device *dev, @@ -42,6 +76,7 @@ static inline void msm_mmu_init(struct msm_mmu *mmu, struct device *dev, struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks); struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsigned long quirks); +struct msm_mmu *msm_iommu_disp_new(struct device *dev, unsigned long quirks); static inline void msm_mmu_set_fault_handler(struct msm_mmu *mmu, void *arg, int (*handler)(void *arg, unsigned long iova, int flags, void *data)) @@ -50,10 +85,11 @@ static inline void msm_mmu_set_fault_handler(struct msm_mmu *mmu, void *arg, mmu->handler = handler; } -struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent); +struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_managed); int msm_iommu_pagetable_params(struct msm_mmu *mmu, phys_addr_t *ttbr, - int *asid); + int *asid); +int msm_iommu_pagetable_walk(struct msm_mmu *mmu, unsigned long iova, uint64_t ptes[4]); struct iommu_domain_geometry *msm_iommu_get_geometry(struct msm_mmu *mmu); #endif /* __MSM_MMU_H__ */ diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c index 39138e190cb9..54493a94dcb7 100644 --- a/drivers/gpu/drm/msm/msm_rd.c +++ b/drivers/gpu/drm/msm/msm_rd.c @@ -308,21 +308,11 @@ void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) priv->hangrd = NULL; } -static void snapshot_buf(struct msm_rd_state *rd, - struct msm_gem_submit *submit, int idx, - uint64_t iova, uint32_t size, bool full) +static void snapshot_buf(struct msm_rd_state *rd, struct drm_gem_object *obj, + uint64_t iova, bool full, size_t offset, size_t size) { - struct drm_gem_object *obj = submit->bos[idx].obj; - unsigned offset = 0; const char *buf; - if (iova) { - offset = iova - submit->bos[idx].iova; - } else { - iova = submit->bos[idx].iova; - size = obj->size; - } - /* * Always write the GPUADDR header so can get a complete list of all the * buffers in the cmd @@ -333,10 +323,6 @@ static void snapshot_buf(struct msm_rd_state *rd, if (!full) return; - /* But only dump the contents of buffers marked READ */ - if (!(submit->bos[idx].flags & MSM_SUBMIT_BO_READ)) - return; - buf = msm_gem_get_vaddr_active(obj); if (IS_ERR(buf)) return; @@ -352,6 +338,7 @@ static void snapshot_buf(struct msm_rd_state *rd, void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, const char *fmt, ...) { + extern bool rd_full; struct task_struct *task; char msg[256]; int i, n; @@ -385,16 +372,43 @@ void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4)); - for (i = 0; i < submit->nr_bos; i++) - snapshot_buf(rd, submit, i, 0, 0, should_dump(submit, i)); + if (msm_context_is_vmbind(submit->queue->ctx)) { + struct drm_gpuva *vma; - for (i = 0; i < submit->nr_cmds; i++) { - uint32_t szd = submit->cmd[i].size; /* in dwords */ + drm_gpuvm_resv_assert_held(submit->vm); + + drm_gpuvm_for_each_va (vma, submit->vm) { + bool dump = rd_full || (vma->flags & MSM_VMA_DUMP); + + /* Skip MAP_NULL/PRR VMAs: */ + if (!vma->gem.obj) + continue; + + snapshot_buf(rd, vma->gem.obj, vma->va.addr, dump, + vma->gem.offset, vma->va.range); + } + + } else { + for (i = 0; i < submit->nr_bos; i++) { + struct drm_gem_object *obj = submit->bos[i].obj; + bool dump = rd_full || (submit->bos[i].flags & MSM_SUBMIT_BO_DUMP); + + snapshot_buf(rd, obj, submit->bos[i].iova, dump, 0, obj->size); + } + + for (i = 0; i < submit->nr_cmds; i++) { + uint32_t szd = submit->cmd[i].size; /* in dwords */ + int idx = submit->cmd[i].idx; + bool dump = rd_full || (submit->bos[idx].flags & MSM_SUBMIT_BO_DUMP); + + /* snapshot cmdstream bo's (if we haven't already): */ + if (!dump) { + struct drm_gem_object *obj = submit->bos[idx].obj; + size_t offset = submit->cmd[i].iova - submit->bos[idx].iova; - /* snapshot cmdstream bo's (if we haven't already): */ - if (!should_dump(submit, i)) { - snapshot_buf(rd, submit, submit->cmd[i].idx, - submit->cmd[i].iova, szd * 4, true); + snapshot_buf(rd, obj, submit->cmd[i].iova, true, + offset, szd * 4); + } } } diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index c803556a8f64..b2f612e5dc79 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -17,6 +17,7 @@ static struct dma_fence *msm_job_run(struct drm_sched_job *job) struct msm_fence_context *fctx = submit->ring->fctx; struct msm_gpu *gpu = submit->gpu; struct msm_drm_private *priv = gpu->dev->dev_private; + unsigned nr_cmds = submit->nr_cmds; int i; msm_fence_init(submit->hw_fence, fctx); @@ -36,8 +37,13 @@ static struct dma_fence *msm_job_run(struct drm_sched_job *job) /* TODO move submit path over to using a per-ring lock.. */ mutex_lock(&gpu->lock); + if (submit->queue->ctx->closed) + submit->nr_cmds = 0; + msm_gpu_submit(gpu, submit); + submit->nr_cmds = nr_cmds; + mutex_unlock(&gpu->lock); return dma_fence_get(submit->hw_fence); @@ -59,8 +65,14 @@ static const struct drm_sched_backend_ops msm_sched_ops = { struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, void *memptrs, uint64_t memptrs_iova) { + struct drm_sched_init_args args = { + .ops = &msm_sched_ops, + .num_rqs = DRM_SCHED_PRIORITY_COUNT, + .credit_limit = num_hw_submissions, + .timeout = MAX_SCHEDULE_TIMEOUT, + .dev = gpu->dev->dev, + }; struct msm_ringbuffer *ring; - long sched_timeout; char name[32]; int ret; @@ -78,7 +90,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, ring->start = msm_gem_kernel_new(gpu->dev, MSM_GPU_RINGBUFFER_SZ, check_apriv(gpu, MSM_BO_WC | MSM_BO_GPU_READONLY), - gpu->aspace, &ring->bo, &ring->iova); + gpu->vm, &ring->bo, &ring->iova); if (IS_ERR(ring->start)) { ret = PTR_ERR(ring->start); @@ -87,6 +99,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, } msm_gem_object_set_name(ring->bo, "ring%d", id); + args.name = to_msm_bo(ring->bo)->name; ring->end = ring->start + (MSM_GPU_RINGBUFFER_SZ >> 2); ring->next = ring->start; @@ -95,13 +108,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, ring->memptrs = memptrs; ring->memptrs_iova = memptrs_iova; - /* currently managing hangcheck ourselves: */ - sched_timeout = MAX_SCHEDULE_TIMEOUT; - - ret = drm_sched_init(&ring->sched, &msm_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - num_hw_submissions, 0, sched_timeout, - NULL, NULL, to_msm_bo(ring->bo)->name, gpu->dev->dev); + ret = drm_sched_init(&ring->sched, &args); if (ret) { goto fail; } @@ -130,7 +137,7 @@ void msm_ringbuffer_destroy(struct msm_ringbuffer *ring) msm_fence_context_free(ring->fctx); - msm_gem_kernel_put(ring->bo, ring->gpu->aspace); + msm_gem_kernel_put(ring->bo, ring->gpu->vm); kfree(ring); } diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c index 2fc3eaf81f44..d53dfad16bde 100644 --- a/drivers/gpu/drm/msm/msm_submitqueue.c +++ b/drivers/gpu/drm/msm/msm_submitqueue.c @@ -7,8 +7,7 @@ #include "msm_gpu.h" -int msm_file_private_set_sysprof(struct msm_file_private *ctx, - struct msm_gpu *gpu, int sysprof) +int msm_context_set_sysprof(struct msm_context *ctx, struct msm_gpu *gpu, int sysprof) { /* * Since pm_runtime and sysprof_active are both refcounts, we @@ -18,7 +17,7 @@ int msm_file_private_set_sysprof(struct msm_file_private *ctx, switch (sysprof) { default: - return -EINVAL; + return UERR(EINVAL, gpu->dev, "Invalid sysprof: %d", sysprof); case 2: pm_runtime_get_sync(&gpu->pdev->dev); fallthrough; @@ -41,15 +40,19 @@ int msm_file_private_set_sysprof(struct msm_file_private *ctx, break; } + /* Some gpu families require additional setup for sysprof */ + if (gpu->funcs->sysprof_setup) + gpu->funcs->sysprof_setup(gpu); + ctx->sysprof = sysprof; return 0; } -void __msm_file_private_destroy(struct kref *kref) +void __msm_context_destroy(struct kref *kref) { - struct msm_file_private *ctx = container_of(kref, - struct msm_file_private, ref); + struct msm_context *ctx = container_of(kref, + struct msm_context, ref); int i; for (i = 0; i < ARRAY_SIZE(ctx->entities); i++) { @@ -60,7 +63,7 @@ void __msm_file_private_destroy(struct kref *kref) kfree(ctx->entities[i]); } - msm_gem_address_space_put(ctx->aspace); + drm_gpuvm_put(ctx->vm); kfree(ctx->comm); kfree(ctx->cmdline); kfree(ctx); @@ -73,12 +76,15 @@ void msm_submitqueue_destroy(struct kref *kref) idr_destroy(&queue->fence_idr); - msm_file_private_put(queue->ctx); + if (queue->entity == &queue->_vm_bind_entity[0]) + drm_sched_entity_destroy(queue->entity); + + msm_context_put(queue->ctx); kfree(queue); } -struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx, +struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_context *ctx, u32 id) { struct msm_gpu_submitqueue *entry; @@ -101,9 +107,9 @@ struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx, return NULL; } -void msm_submitqueue_close(struct msm_file_private *ctx) +void msm_submitqueue_close(struct msm_context *ctx) { - struct msm_gpu_submitqueue *entry, *tmp; + struct msm_gpu_submitqueue *queue, *tmp; if (!ctx) return; @@ -112,14 +118,21 @@ void msm_submitqueue_close(struct msm_file_private *ctx) * No lock needed in close and there won't * be any more user ioctls coming our way */ - list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node) { - list_del(&entry->node); - msm_submitqueue_put(entry); + list_for_each_entry_safe(queue, tmp, &ctx->submitqueues, node) { + if (queue->entity == &queue->_vm_bind_entity[0]) + drm_sched_entity_flush(queue->entity, MAX_WAIT_SCHED_ENTITY_Q_EMPTY); + list_del(&queue->node); + msm_submitqueue_put(queue); } + + if (!ctx->vm) + return; + + msm_gem_vm_close(ctx->vm); } static struct drm_sched_entity * -get_sched_entity(struct msm_file_private *ctx, struct msm_ringbuffer *ring, +get_sched_entity(struct msm_context *ctx, struct msm_ringbuffer *ring, unsigned ring_nr, enum drm_sched_priority sched_prio) { static DEFINE_MUTEX(entity_lock); @@ -155,14 +168,12 @@ get_sched_entity(struct msm_file_private *ctx, struct msm_ringbuffer *ring, return ctx->entities[idx]; } -int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, +int msm_submitqueue_create(struct drm_device *drm, struct msm_context *ctx, u32 prio, u32 flags, u32 *id) { struct msm_drm_private *priv = drm->dev_private; struct msm_gpu_submitqueue *queue; enum drm_sched_priority sched_prio; - extern int enable_preemption; - bool preemption_supported; unsigned ring_nr; int ret; @@ -172,26 +183,53 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, if (!priv->gpu) return -ENODEV; - preemption_supported = priv->gpu->nr_rings == 1 && enable_preemption != 0; + if (flags & MSM_SUBMITQUEUE_VM_BIND) { + unsigned sz; - if (flags & MSM_SUBMITQUEUE_ALLOW_PREEMPT && preemption_supported) - return -EINVAL; + /* Not allowed for kernel managed VMs (ie. kernel allocs VA) */ + if (!msm_context_is_vmbind(ctx)) + return -EINVAL; - ret = msm_gpu_convert_priority(priv->gpu, prio, &ring_nr, &sched_prio); - if (ret) - return ret; + if (prio) + return -EINVAL; + + sz = struct_size(queue, _vm_bind_entity, 1); + queue = kzalloc(sz, GFP_KERNEL); + } else { + extern int enable_preemption; + bool preemption_supported = + priv->gpu->nr_rings == 1 && enable_preemption != 0; - queue = kzalloc(sizeof(*queue), GFP_KERNEL); + if (flags & MSM_SUBMITQUEUE_ALLOW_PREEMPT && preemption_supported) + return -EINVAL; + + ret = msm_gpu_convert_priority(priv->gpu, prio, &ring_nr, &sched_prio); + if (ret) + return ret; + + queue = kzalloc(sizeof(*queue), GFP_KERNEL); + } if (!queue) return -ENOMEM; kref_init(&queue->ref); queue->flags = flags; - queue->ring_nr = ring_nr; - queue->entity = get_sched_entity(ctx, priv->gpu->rb[ring_nr], - ring_nr, sched_prio); + if (flags & MSM_SUBMITQUEUE_VM_BIND) { + struct drm_gpu_scheduler *sched = &to_msm_vm(msm_context_vm(drm, ctx))->sched; + + queue->entity = &queue->_vm_bind_entity[0]; + + drm_sched_entity_init(queue->entity, DRM_SCHED_PRIORITY_KERNEL, + &sched, 1, NULL); + } else { + queue->ring_nr = ring_nr; + + queue->entity = get_sched_entity(ctx, priv->gpu->rb[ring_nr], + ring_nr, sched_prio); + } + if (IS_ERR(queue->entity)) { ret = PTR_ERR(queue->entity); kfree(queue); @@ -200,7 +238,7 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, write_lock(&ctx->queuelock); - queue->ctx = msm_file_private_get(ctx); + queue->ctx = msm_context_get(ctx); queue->id = ctx->queueid++; if (id) @@ -221,7 +259,7 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, * Create the default submit-queue (id==0), used for backwards compatibility * for userspace that pre-dates the introduction of submitqueues. */ -int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx) +int msm_submitqueue_init(struct drm_device *drm, struct msm_context *ctx) { struct msm_drm_private *priv = drm->dev_private; int default_prio, max_priority; @@ -261,7 +299,7 @@ static int msm_submitqueue_query_faults(struct msm_gpu_submitqueue *queue, return ret ? -EFAULT : 0; } -int msm_submitqueue_query(struct drm_device *drm, struct msm_file_private *ctx, +int msm_submitqueue_query(struct drm_device *drm, struct msm_context *ctx, struct drm_msm_submitqueue_query *args) { struct msm_gpu_submitqueue *queue; @@ -282,7 +320,7 @@ int msm_submitqueue_query(struct drm_device *drm, struct msm_file_private *ctx, return ret; } -int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id) +int msm_submitqueue_remove(struct msm_context *ctx, u32 id) { struct msm_gpu_submitqueue *entry; diff --git a/drivers/gpu/drm/msm/msm_syncobj.c b/drivers/gpu/drm/msm/msm_syncobj.c new file mode 100644 index 000000000000..4baa9f522c54 --- /dev/null +++ b/drivers/gpu/drm/msm/msm_syncobj.c @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (C) 2020 Google, Inc */ + +#include "drm/drm_drv.h" + +#include "msm_drv.h" +#include "msm_syncobj.h" + +struct drm_syncobj ** +msm_syncobj_parse_deps(struct drm_device *dev, + struct drm_sched_job *job, + struct drm_file *file, + uint64_t in_syncobjs_addr, + uint32_t nr_in_syncobjs, + size_t syncobj_stride) +{ + struct drm_syncobj **syncobjs = NULL; + struct drm_msm_syncobj syncobj_desc = {0}; + int ret = 0; + uint32_t i, j; + + syncobjs = kcalloc(nr_in_syncobjs, sizeof(*syncobjs), + GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); + if (!syncobjs) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < nr_in_syncobjs; ++i) { + uint64_t address = in_syncobjs_addr + i * syncobj_stride; + + if (copy_from_user(&syncobj_desc, + u64_to_user_ptr(address), + min(syncobj_stride, sizeof(syncobj_desc)))) { + ret = -EFAULT; + break; + } + + if (syncobj_desc.point && + !drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) { + ret = UERR(EOPNOTSUPP, dev, "syncobj timeline unsupported"); + break; + } + + if (syncobj_desc.flags & ~MSM_SYNCOBJ_FLAGS) { + ret = UERR(EINVAL, dev, "invalid syncobj flags: %x", syncobj_desc.flags); + break; + } + + ret = drm_sched_job_add_syncobj_dependency(job, file, + syncobj_desc.handle, + syncobj_desc.point); + if (ret) + break; + + if (syncobj_desc.flags & MSM_SYNCOBJ_RESET) { + syncobjs[i] = drm_syncobj_find(file, syncobj_desc.handle); + if (!syncobjs[i]) { + ret = UERR(EINVAL, dev, "invalid syncobj handle: %u", i); + break; + } + } + } + + if (ret) { + for (j = 0; j <= i; ++j) { + if (syncobjs[j]) + drm_syncobj_put(syncobjs[j]); + } + kfree(syncobjs); + return ERR_PTR(ret); + } + return syncobjs; +} + +void +msm_syncobj_reset(struct drm_syncobj **syncobjs, uint32_t nr_syncobjs) +{ + uint32_t i; + + for (i = 0; syncobjs && i < nr_syncobjs; ++i) { + if (syncobjs[i]) + drm_syncobj_replace_fence(syncobjs[i], NULL); + } +} + +struct msm_syncobj_post_dep * +msm_syncobj_parse_post_deps(struct drm_device *dev, + struct drm_file *file, + uint64_t syncobjs_addr, + uint32_t nr_syncobjs, + size_t syncobj_stride) +{ + struct msm_syncobj_post_dep *post_deps; + struct drm_msm_syncobj syncobj_desc = {0}; + int ret = 0; + uint32_t i, j; + + post_deps = kcalloc(nr_syncobjs, sizeof(*post_deps), + GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); + if (!post_deps) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < nr_syncobjs; ++i) { + uint64_t address = syncobjs_addr + i * syncobj_stride; + + if (copy_from_user(&syncobj_desc, + u64_to_user_ptr(address), + min(syncobj_stride, sizeof(syncobj_desc)))) { + ret = -EFAULT; + break; + } + + post_deps[i].point = syncobj_desc.point; + + if (syncobj_desc.flags) { + ret = UERR(EINVAL, dev, "invalid syncobj flags"); + break; + } + + if (syncobj_desc.point) { + if (!drm_core_check_feature(dev, + DRIVER_SYNCOBJ_TIMELINE)) { + ret = UERR(EOPNOTSUPP, dev, "syncobj timeline unsupported"); + break; + } + + post_deps[i].chain = dma_fence_chain_alloc(); + if (!post_deps[i].chain) { + ret = -ENOMEM; + break; + } + } + + post_deps[i].syncobj = + drm_syncobj_find(file, syncobj_desc.handle); + if (!post_deps[i].syncobj) { + ret = UERR(EINVAL, dev, "invalid syncobj handle"); + break; + } + } + + if (ret) { + for (j = 0; j <= i; ++j) { + dma_fence_chain_free(post_deps[j].chain); + if (post_deps[j].syncobj) + drm_syncobj_put(post_deps[j].syncobj); + } + + kfree(post_deps); + return ERR_PTR(ret); + } + + return post_deps; +} + +void +msm_syncobj_process_post_deps(struct msm_syncobj_post_dep *post_deps, + uint32_t count, struct dma_fence *fence) +{ + uint32_t i; + + for (i = 0; post_deps && i < count; ++i) { + if (post_deps[i].chain) { + drm_syncobj_add_point(post_deps[i].syncobj, + post_deps[i].chain, + fence, post_deps[i].point); + post_deps[i].chain = NULL; + } else { + drm_syncobj_replace_fence(post_deps[i].syncobj, + fence); + } + } +} diff --git a/drivers/gpu/drm/msm/msm_syncobj.h b/drivers/gpu/drm/msm/msm_syncobj.h new file mode 100644 index 000000000000..bcaa15d01da0 --- /dev/null +++ b/drivers/gpu/drm/msm/msm_syncobj.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (C) 2020 Google, Inc */ + +#ifndef __MSM_GEM_SYNCOBJ_H__ +#define __MSM_GEM_SYNCOBJ_H__ + +#include "drm/drm_device.h" +#include "drm/drm_syncobj.h" +#include "drm/gpu_scheduler.h" + +struct msm_syncobj_post_dep { + struct drm_syncobj *syncobj; + uint64_t point; + struct dma_fence_chain *chain; +}; + +struct drm_syncobj ** +msm_syncobj_parse_deps(struct drm_device *dev, + struct drm_sched_job *job, + struct drm_file *file, + uint64_t in_syncobjs_addr, + uint32_t nr_in_syncobjs, + size_t syncobj_stride); + +void msm_syncobj_reset(struct drm_syncobj **syncobjs, uint32_t nr_syncobjs); + +struct msm_syncobj_post_dep * +msm_syncobj_parse_post_deps(struct drm_device *dev, + struct drm_file *file, + uint64_t syncobjs_addr, + uint32_t nr_syncobjs, + size_t syncobj_stride); + +void msm_syncobj_process_post_deps(struct msm_syncobj_post_dep *post_deps, + uint32_t count, struct dma_fence *fence); + +#endif /* __MSM_GEM_SYNCOBJ_H__ */ diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml index 2db425abf0f3..3941e7510754 100644 --- a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml +++ b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml @@ -5,6 +5,13 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <import file="freedreno_copyright.xml"/> <import file="adreno/adreno_common.xml"/> <import file="adreno/adreno_pm4.xml"/> +<import file="adreno/a6xx_enums.xml"/> +<import file="adreno/a7xx_enums.xml"/> +<import file="adreno/a8xx_enums.xml"/> +<import file="adreno/a6xx_perfcntrs.xml"/> +<import file="adreno/a7xx_perfcntrs.xml"/> +<import file="adreno/a6xx_descriptors.xml"/> +<import file="adreno/a8xx_descriptors.xml"/> <!-- Each register that is actually being used by driver should have "usage" defined, @@ -20,2205 +27,6 @@ is either overwritten by renderpass/blit (ib2) or not used if not overwritten by a particular renderpass/blit. --> -<!-- these might be same as a5xx --> -<enum name="a6xx_tile_mode"> - <value name="TILE6_LINEAR" value="0"/> - <value name="TILE6_2" value="2"/> - <value name="TILE6_3" value="3"/> -</enum> - -<enum name="a6xx_format"> - <value value="0x02" name="FMT6_A8_UNORM"/> - <value value="0x03" name="FMT6_8_UNORM"/> - <value value="0x04" name="FMT6_8_SNORM"/> - <value value="0x05" name="FMT6_8_UINT"/> - <value value="0x06" name="FMT6_8_SINT"/> - - <value value="0x08" name="FMT6_4_4_4_4_UNORM"/> - <value value="0x0a" name="FMT6_5_5_5_1_UNORM"/> - <value value="0x0c" name="FMT6_1_5_5_5_UNORM"/> <!-- read only --> - <value value="0x0e" name="FMT6_5_6_5_UNORM"/> - - <value value="0x0f" name="FMT6_8_8_UNORM"/> - <value value="0x10" name="FMT6_8_8_SNORM"/> - <value value="0x11" name="FMT6_8_8_UINT"/> - <value value="0x12" name="FMT6_8_8_SINT"/> - <value value="0x13" name="FMT6_L8_A8_UNORM"/> - - <value value="0x15" name="FMT6_16_UNORM"/> - <value value="0x16" name="FMT6_16_SNORM"/> - <value value="0x17" name="FMT6_16_FLOAT"/> - <value value="0x18" name="FMT6_16_UINT"/> - <value value="0x19" name="FMT6_16_SINT"/> - - <value value="0x21" name="FMT6_8_8_8_UNORM"/> - <value value="0x22" name="FMT6_8_8_8_SNORM"/> - <value value="0x23" name="FMT6_8_8_8_UINT"/> - <value value="0x24" name="FMT6_8_8_8_SINT"/> - - <value value="0x30" name="FMT6_8_8_8_8_UNORM"/> - <value value="0x31" name="FMT6_8_8_8_X8_UNORM"/> <!-- samples 1 for alpha --> - <value value="0x32" name="FMT6_8_8_8_8_SNORM"/> - <value value="0x33" name="FMT6_8_8_8_8_UINT"/> - <value value="0x34" name="FMT6_8_8_8_8_SINT"/> - - <value value="0x35" name="FMT6_9_9_9_E5_FLOAT"/> - - <value value="0x36" name="FMT6_10_10_10_2_UNORM"/> - <value value="0x37" name="FMT6_10_10_10_2_UNORM_DEST"/> - <value value="0x39" name="FMT6_10_10_10_2_SNORM"/> - <value value="0x3a" name="FMT6_10_10_10_2_UINT"/> - <value value="0x3b" name="FMT6_10_10_10_2_SINT"/> - - <value value="0x42" name="FMT6_11_11_10_FLOAT"/> - - <value value="0x43" name="FMT6_16_16_UNORM"/> - <value value="0x44" name="FMT6_16_16_SNORM"/> - <value value="0x45" name="FMT6_16_16_FLOAT"/> - <value value="0x46" name="FMT6_16_16_UINT"/> - <value value="0x47" name="FMT6_16_16_SINT"/> - - <value value="0x48" name="FMT6_32_UNORM"/> - <value value="0x49" name="FMT6_32_SNORM"/> - <value value="0x4a" name="FMT6_32_FLOAT"/> - <value value="0x4b" name="FMT6_32_UINT"/> - <value value="0x4c" name="FMT6_32_SINT"/> - <value value="0x4d" name="FMT6_32_FIXED"/> - - <value value="0x58" name="FMT6_16_16_16_UNORM"/> - <value value="0x59" name="FMT6_16_16_16_SNORM"/> - <value value="0x5a" name="FMT6_16_16_16_FLOAT"/> - <value value="0x5b" name="FMT6_16_16_16_UINT"/> - <value value="0x5c" name="FMT6_16_16_16_SINT"/> - - <value value="0x60" name="FMT6_16_16_16_16_UNORM"/> - <value value="0x61" name="FMT6_16_16_16_16_SNORM"/> - <value value="0x62" name="FMT6_16_16_16_16_FLOAT"/> - <value value="0x63" name="FMT6_16_16_16_16_UINT"/> - <value value="0x64" name="FMT6_16_16_16_16_SINT"/> - - <value value="0x65" name="FMT6_32_32_UNORM"/> - <value value="0x66" name="FMT6_32_32_SNORM"/> - <value value="0x67" name="FMT6_32_32_FLOAT"/> - <value value="0x68" name="FMT6_32_32_UINT"/> - <value value="0x69" name="FMT6_32_32_SINT"/> - <value value="0x6a" name="FMT6_32_32_FIXED"/> - - <value value="0x70" name="FMT6_32_32_32_UNORM"/> - <value value="0x71" name="FMT6_32_32_32_SNORM"/> - <value value="0x72" name="FMT6_32_32_32_UINT"/> - <value value="0x73" name="FMT6_32_32_32_SINT"/> - <value value="0x74" name="FMT6_32_32_32_FLOAT"/> - <value value="0x75" name="FMT6_32_32_32_FIXED"/> - - <value value="0x80" name="FMT6_32_32_32_32_UNORM"/> - <value value="0x81" name="FMT6_32_32_32_32_SNORM"/> - <value value="0x82" name="FMT6_32_32_32_32_FLOAT"/> - <value value="0x83" name="FMT6_32_32_32_32_UINT"/> - <value value="0x84" name="FMT6_32_32_32_32_SINT"/> - <value value="0x85" name="FMT6_32_32_32_32_FIXED"/> - - <value value="0x8c" name="FMT6_G8R8B8R8_422_UNORM"/> <!-- UYVY --> - <value value="0x8d" name="FMT6_R8G8R8B8_422_UNORM"/> <!-- YUYV --> - <value value="0x8e" name="FMT6_R8_G8B8_2PLANE_420_UNORM"/> <!-- NV12 --> - <value value="0x8f" name="FMT6_NV21"/> - <value value="0x90" name="FMT6_R8_G8_B8_3PLANE_420_UNORM"/> <!-- YV12 --> - - <value value="0x91" name="FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8"/> - - <!-- Note: tiling/UBWC for these may be different from equivalent formats - For example FMT6_NV12_Y is not compatible with FMT6_8_UNORM - --> - <value value="0x94" name="FMT6_NV12_Y"/> - <value value="0x95" name="FMT6_NV12_UV"/> - <value value="0x96" name="FMT6_NV12_VU"/> - <value value="0x97" name="FMT6_NV12_4R"/> - <value value="0x98" name="FMT6_NV12_4R_Y"/> - <value value="0x99" name="FMT6_NV12_4R_UV"/> - <value value="0x9a" name="FMT6_P010"/> - <value value="0x9b" name="FMT6_P010_Y"/> - <value value="0x9c" name="FMT6_P010_UV"/> - <value value="0x9d" name="FMT6_TP10"/> - <value value="0x9e" name="FMT6_TP10_Y"/> - <value value="0x9f" name="FMT6_TP10_UV"/> - - <value value="0xa0" name="FMT6_Z24_UNORM_S8_UINT"/> - - <value value="0xab" name="FMT6_ETC2_RG11_UNORM"/> - <value value="0xac" name="FMT6_ETC2_RG11_SNORM"/> - <value value="0xad" name="FMT6_ETC2_R11_UNORM"/> - <value value="0xae" name="FMT6_ETC2_R11_SNORM"/> - <value value="0xaf" name="FMT6_ETC1"/> - <value value="0xb0" name="FMT6_ETC2_RGB8"/> - <value value="0xb1" name="FMT6_ETC2_RGBA8"/> - <value value="0xb2" name="FMT6_ETC2_RGB8A1"/> - <value value="0xb3" name="FMT6_DXT1"/> - <value value="0xb4" name="FMT6_DXT3"/> - <value value="0xb5" name="FMT6_DXT5"/> - <value value="0xb7" name="FMT6_RGTC1_UNORM"/> - <value value="0xb8" name="FMT6_RGTC1_SNORM"/> - <value value="0xbb" name="FMT6_RGTC2_UNORM"/> - <value value="0xbc" name="FMT6_RGTC2_SNORM"/> - <value value="0xbe" name="FMT6_BPTC_UFLOAT"/> - <value value="0xbf" name="FMT6_BPTC_FLOAT"/> - <value value="0xc0" name="FMT6_BPTC"/> - <value value="0xc1" name="FMT6_ASTC_4x4"/> - <value value="0xc2" name="FMT6_ASTC_5x4"/> - <value value="0xc3" name="FMT6_ASTC_5x5"/> - <value value="0xc4" name="FMT6_ASTC_6x5"/> - <value value="0xc5" name="FMT6_ASTC_6x6"/> - <value value="0xc6" name="FMT6_ASTC_8x5"/> - <value value="0xc7" name="FMT6_ASTC_8x6"/> - <value value="0xc8" name="FMT6_ASTC_8x8"/> - <value value="0xc9" name="FMT6_ASTC_10x5"/> - <value value="0xca" name="FMT6_ASTC_10x6"/> - <value value="0xcb" name="FMT6_ASTC_10x8"/> - <value value="0xcc" name="FMT6_ASTC_10x10"/> - <value value="0xcd" name="FMT6_ASTC_12x10"/> - <value value="0xce" name="FMT6_ASTC_12x12"/> - - <!-- for sampling stencil (integer, 2nd channel), not available on a630 --> - <value value="0xea" name="FMT6_Z24_UINT_S8_UINT"/> - - <!-- Not a hw enum, used internally in driver --> - <value value="0xff" name="FMT6_NONE"/> - -</enum> - -<!-- probably same as a5xx --> -<enum name="a6xx_polygon_mode"> - <value name="POLYMODE6_POINTS" value="1"/> - <value name="POLYMODE6_LINES" value="2"/> - <value name="POLYMODE6_TRIANGLES" value="3"/> -</enum> - -<enum name="a6xx_depth_format"> - <value name="DEPTH6_NONE" value="0"/> - <value name="DEPTH6_16" value="1"/> - <value name="DEPTH6_24_8" value="2"/> - <value name="DEPTH6_32" value="4"/> -</enum> - -<bitset name="a6x_cp_protect" inline="yes"> - <bitfield name="BASE_ADDR" low="0" high="17"/> - <bitfield name="MASK_LEN" low="18" high="30"/> - <bitfield name="READ" pos="31" type="boolean"/> -</bitset> - -<enum name="a6xx_shader_id"> - <value value="0x9" name="A6XX_TP0_TMO_DATA"/> - <value value="0xa" name="A6XX_TP0_SMO_DATA"/> - <value value="0xb" name="A6XX_TP0_MIPMAP_BASE_DATA"/> - <value value="0x19" name="A6XX_TP1_TMO_DATA"/> - <value value="0x1a" name="A6XX_TP1_SMO_DATA"/> - <value value="0x1b" name="A6XX_TP1_MIPMAP_BASE_DATA"/> - <value value="0x29" name="A6XX_SP_INST_DATA"/> - <value value="0x2a" name="A6XX_SP_LB_0_DATA"/> - <value value="0x2b" name="A6XX_SP_LB_1_DATA"/> - <value value="0x2c" name="A6XX_SP_LB_2_DATA"/> - <value value="0x2d" name="A6XX_SP_LB_3_DATA"/> - <value value="0x2e" name="A6XX_SP_LB_4_DATA"/> - <value value="0x2f" name="A6XX_SP_LB_5_DATA"/> - <value value="0x30" name="A6XX_SP_CB_BINDLESS_DATA"/> - <value value="0x31" name="A6XX_SP_CB_LEGACY_DATA"/> - <value value="0x32" name="A6XX_SP_UAV_DATA"/> - <value value="0x33" name="A6XX_SP_INST_TAG"/> - <value value="0x34" name="A6XX_SP_CB_BINDLESS_TAG"/> - <value value="0x35" name="A6XX_SP_TMO_UMO_TAG"/> - <value value="0x36" name="A6XX_SP_SMO_TAG"/> - <value value="0x37" name="A6XX_SP_STATE_DATA"/> - <value value="0x49" name="A6XX_HLSQ_CHUNK_CVS_RAM"/> - <value value="0x4a" name="A6XX_HLSQ_CHUNK_CPS_RAM"/> - <value value="0x4b" name="A6XX_HLSQ_CHUNK_CVS_RAM_TAG"/> - <value value="0x4c" name="A6XX_HLSQ_CHUNK_CPS_RAM_TAG"/> - <value value="0x4d" name="A6XX_HLSQ_ICB_CVS_CB_BASE_TAG"/> - <value value="0x4e" name="A6XX_HLSQ_ICB_CPS_CB_BASE_TAG"/> - <value value="0x50" name="A6XX_HLSQ_CVS_MISC_RAM"/> - <value value="0x51" name="A6XX_HLSQ_CPS_MISC_RAM"/> - <value value="0x52" name="A6XX_HLSQ_INST_RAM"/> - <value value="0x53" name="A6XX_HLSQ_GFX_CVS_CONST_RAM"/> - <value value="0x54" name="A6XX_HLSQ_GFX_CPS_CONST_RAM"/> - <value value="0x55" name="A6XX_HLSQ_CVS_MISC_RAM_TAG"/> - <value value="0x56" name="A6XX_HLSQ_CPS_MISC_RAM_TAG"/> - <value value="0x57" name="A6XX_HLSQ_INST_RAM_TAG"/> - <value value="0x58" name="A6XX_HLSQ_GFX_CVS_CONST_RAM_TAG"/> - <value value="0x59" name="A6XX_HLSQ_GFX_CPS_CONST_RAM_TAG"/> - <value value="0x5a" name="A6XX_HLSQ_PWR_REST_RAM"/> - <value value="0x5b" name="A6XX_HLSQ_PWR_REST_TAG"/> - <value value="0x60" name="A6XX_HLSQ_DATAPATH_META"/> - <value value="0x61" name="A6XX_HLSQ_FRONTEND_META"/> - <value value="0x62" name="A6XX_HLSQ_INDIRECT_META"/> - <value value="0x63" name="A6XX_HLSQ_BACKEND_META"/> - <value value="0x70" name="A6XX_SP_LB_6_DATA"/> - <value value="0x71" name="A6XX_SP_LB_7_DATA"/> - <value value="0x73" name="A6XX_HLSQ_INST_RAM_1"/> -</enum> - -<enum name="a7xx_statetype_id"> - <value value="0" name="A7XX_TP0_NCTX_REG"/> - <value value="1" name="A7XX_TP0_CTX0_3D_CVS_REG"/> - <value value="2" name="A7XX_TP0_CTX0_3D_CPS_REG"/> - <value value="3" name="A7XX_TP0_CTX1_3D_CVS_REG"/> - <value value="4" name="A7XX_TP0_CTX1_3D_CPS_REG"/> - <value value="5" name="A7XX_TP0_CTX2_3D_CPS_REG"/> - <value value="6" name="A7XX_TP0_CTX3_3D_CPS_REG"/> - <value value="9" name="A7XX_TP0_TMO_DATA"/> - <value value="10" name="A7XX_TP0_SMO_DATA"/> - <value value="11" name="A7XX_TP0_MIPMAP_BASE_DATA"/> - <value value="32" name="A7XX_SP_NCTX_REG"/> - <value value="33" name="A7XX_SP_CTX0_3D_CVS_REG"/> - <value value="34" name="A7XX_SP_CTX0_3D_CPS_REG"/> - <value value="35" name="A7XX_SP_CTX1_3D_CVS_REG"/> - <value value="36" name="A7XX_SP_CTX1_3D_CPS_REG"/> - <value value="37" name="A7XX_SP_CTX2_3D_CPS_REG"/> - <value value="38" name="A7XX_SP_CTX3_3D_CPS_REG"/> - <value value="39" name="A7XX_SP_INST_DATA"/> - <value value="40" name="A7XX_SP_INST_DATA_1"/> - <value value="41" name="A7XX_SP_LB_0_DATA"/> - <value value="42" name="A7XX_SP_LB_1_DATA"/> - <value value="43" name="A7XX_SP_LB_2_DATA"/> - <value value="44" name="A7XX_SP_LB_3_DATA"/> - <value value="45" name="A7XX_SP_LB_4_DATA"/> - <value value="46" name="A7XX_SP_LB_5_DATA"/> - <value value="47" name="A7XX_SP_LB_6_DATA"/> - <value value="48" name="A7XX_SP_LB_7_DATA"/> - <value value="49" name="A7XX_SP_CB_RAM"/> - <value value="50" name="A7XX_SP_LB_13_DATA"/> - <value value="51" name="A7XX_SP_LB_14_DATA"/> - <value value="52" name="A7XX_SP_INST_TAG"/> - <value value="53" name="A7XX_SP_INST_DATA_2"/> - <value value="54" name="A7XX_SP_TMO_TAG"/> - <value value="55" name="A7XX_SP_SMO_TAG"/> - <value value="56" name="A7XX_SP_STATE_DATA"/> - <value value="57" name="A7XX_SP_HWAVE_RAM"/> - <value value="58" name="A7XX_SP_L0_INST_BUF"/> - <value value="59" name="A7XX_SP_LB_8_DATA"/> - <value value="60" name="A7XX_SP_LB_9_DATA"/> - <value value="61" name="A7XX_SP_LB_10_DATA"/> - <value value="62" name="A7XX_SP_LB_11_DATA"/> - <value value="63" name="A7XX_SP_LB_12_DATA"/> - <value value="64" name="A7XX_HLSQ_DATAPATH_DSTR_META"/> - <value value="67" name="A7XX_HLSQ_L2STC_TAG_RAM"/> - <value value="68" name="A7XX_HLSQ_L2STC_INFO_CMD"/> - <value value="69" name="A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG"/> - <value value="70" name="A7XX_HLSQ_CPS_BE_CTXT_BUF_RAM_TAG"/> - <value value="71" name="A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM"/> - <value value="72" name="A7XX_HLSQ_GFX_CPS_BE_CTXT_BUF_RAM"/> - <value value="73" name="A7XX_HLSQ_CHUNK_CVS_RAM"/> - <value value="74" name="A7XX_HLSQ_CHUNK_CPS_RAM"/> - <value value="75" name="A7XX_HLSQ_CHUNK_CVS_RAM_TAG"/> - <value value="76" name="A7XX_HLSQ_CHUNK_CPS_RAM_TAG"/> - <value value="77" name="A7XX_HLSQ_ICB_CVS_CB_BASE_TAG"/> - <value value="78" name="A7XX_HLSQ_ICB_CPS_CB_BASE_TAG"/> - <value value="79" name="A7XX_HLSQ_CVS_MISC_RAM"/> - <value value="80" name="A7XX_HLSQ_CPS_MISC_RAM"/> - <value value="81" name="A7XX_HLSQ_CPS_MISC_RAM_1"/> - <value value="82" name="A7XX_HLSQ_INST_RAM"/> - <value value="83" name="A7XX_HLSQ_GFX_CVS_CONST_RAM"/> - <value value="84" name="A7XX_HLSQ_GFX_CPS_CONST_RAM"/> - <value value="85" name="A7XX_HLSQ_CVS_MISC_RAM_TAG"/> - <value value="86" name="A7XX_HLSQ_CPS_MISC_RAM_TAG"/> - <value value="87" name="A7XX_HLSQ_INST_RAM_TAG"/> - <value value="88" name="A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG"/> - <value value="89" name="A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG"/> - <value value="90" name="A7XX_HLSQ_GFX_LOCAL_MISC_RAM"/> - <value value="91" name="A7XX_HLSQ_GFX_LOCAL_MISC_RAM_TAG"/> - <value value="92" name="A7XX_HLSQ_INST_RAM_1"/> - <value value="93" name="A7XX_HLSQ_STPROC_META"/> - <value value="94" name="A7XX_HLSQ_BV_BE_META"/> - <value value="95" name="A7XX_HLSQ_INST_RAM_2"/> - <value value="96" name="A7XX_HLSQ_DATAPATH_META"/> - <value value="97" name="A7XX_HLSQ_FRONTEND_META"/> - <value value="98" name="A7XX_HLSQ_INDIRECT_META"/> - <value value="99" name="A7XX_HLSQ_BACKEND_META"/> -</enum> - -<enum name="a6xx_debugbus_id"> - <value value="0x1" name="A6XX_DBGBUS_CP"/> - <value value="0x2" name="A6XX_DBGBUS_RBBM"/> - <value value="0x3" name="A6XX_DBGBUS_VBIF"/> - <value value="0x4" name="A6XX_DBGBUS_HLSQ"/> - <value value="0x5" name="A6XX_DBGBUS_UCHE"/> - <value value="0x6" name="A6XX_DBGBUS_DPM"/> - <value value="0x7" name="A6XX_DBGBUS_TESS"/> - <value value="0x8" name="A6XX_DBGBUS_PC"/> - <value value="0x9" name="A6XX_DBGBUS_VFDP"/> - <value value="0xa" name="A6XX_DBGBUS_VPC"/> - <value value="0xb" name="A6XX_DBGBUS_TSE"/> - <value value="0xc" name="A6XX_DBGBUS_RAS"/> - <value value="0xd" name="A6XX_DBGBUS_VSC"/> - <value value="0xe" name="A6XX_DBGBUS_COM"/> - <value value="0x10" name="A6XX_DBGBUS_LRZ"/> - <value value="0x11" name="A6XX_DBGBUS_A2D"/> - <value value="0x12" name="A6XX_DBGBUS_CCUFCHE"/> - <value value="0x13" name="A6XX_DBGBUS_GMU_CX"/> - <value value="0x14" name="A6XX_DBGBUS_RBP"/> - <value value="0x15" name="A6XX_DBGBUS_DCS"/> - <value value="0x16" name="A6XX_DBGBUS_DBGC"/> - <value value="0x17" name="A6XX_DBGBUS_CX"/> - <value value="0x18" name="A6XX_DBGBUS_GMU_GX"/> - <value value="0x19" name="A6XX_DBGBUS_TPFCHE"/> - <value value="0x1a" name="A6XX_DBGBUS_GBIF_GX"/> - <value value="0x1d" name="A6XX_DBGBUS_GPC"/> - <value value="0x1e" name="A6XX_DBGBUS_LARC"/> - <value value="0x1f" name="A6XX_DBGBUS_HLSQ_SPTP"/> - <value value="0x20" name="A6XX_DBGBUS_RB_0"/> - <value value="0x21" name="A6XX_DBGBUS_RB_1"/> - <value value="0x22" name="A6XX_DBGBUS_RB_2"/> - <value value="0x24" name="A6XX_DBGBUS_UCHE_WRAPPER"/> - <value value="0x28" name="A6XX_DBGBUS_CCU_0"/> - <value value="0x29" name="A6XX_DBGBUS_CCU_1"/> - <value value="0x2a" name="A6XX_DBGBUS_CCU_2"/> - <value value="0x38" name="A6XX_DBGBUS_VFD_0"/> - <value value="0x39" name="A6XX_DBGBUS_VFD_1"/> - <value value="0x3a" name="A6XX_DBGBUS_VFD_2"/> - <value value="0x3b" name="A6XX_DBGBUS_VFD_3"/> - <value value="0x3c" name="A6XX_DBGBUS_VFD_4"/> - <value value="0x3d" name="A6XX_DBGBUS_VFD_5"/> - <value value="0x40" name="A6XX_DBGBUS_SP_0"/> - <value value="0x41" name="A6XX_DBGBUS_SP_1"/> - <value value="0x42" name="A6XX_DBGBUS_SP_2"/> - <value value="0x48" name="A6XX_DBGBUS_TPL1_0"/> - <value value="0x49" name="A6XX_DBGBUS_TPL1_1"/> - <value value="0x4a" name="A6XX_DBGBUS_TPL1_2"/> - <value value="0x4b" name="A6XX_DBGBUS_TPL1_3"/> - <value value="0x4c" name="A6XX_DBGBUS_TPL1_4"/> - <value value="0x4d" name="A6XX_DBGBUS_TPL1_5"/> - <value value="0x58" name="A6XX_DBGBUS_SPTP_0"/> - <value value="0x59" name="A6XX_DBGBUS_SPTP_1"/> - <value value="0x5a" name="A6XX_DBGBUS_SPTP_2"/> - <value value="0x5b" name="A6XX_DBGBUS_SPTP_3"/> - <value value="0x5c" name="A6XX_DBGBUS_SPTP_4"/> - <value value="0x5d" name="A6XX_DBGBUS_SPTP_5"/> -</enum> - -<enum name="a7xx_state_location"> - <value value="0" name="A7XX_HLSQ_STATE"/> - <value value="1" name="A7XX_HLSQ_DP"/> - <value value="2" name="A7XX_SP_TOP"/> - <value value="3" name="A7XX_USPTP"/> - <value value="4" name="A7XX_HLSQ_DP_STR"/> -</enum> - -<enum name="a7xx_pipe"> - <value value="0" name="A7XX_PIPE_NONE"/> - <value value="1" name="A7XX_PIPE_BR"/> - <value value="2" name="A7XX_PIPE_BV"/> - <value value="3" name="A7XX_PIPE_LPAC"/> -</enum> - -<enum name="a7xx_cluster"> - <value value="0" name="A7XX_CLUSTER_NONE"/> - <value value="1" name="A7XX_CLUSTER_FE"/> - <value value="2" name="A7XX_CLUSTER_SP_VS"/> - <value value="3" name="A7XX_CLUSTER_PC_VS"/> - <value value="4" name="A7XX_CLUSTER_GRAS"/> - <value value="5" name="A7XX_CLUSTER_SP_PS"/> - <value value="6" name="A7XX_CLUSTER_VPC_PS"/> - <value value="7" name="A7XX_CLUSTER_PS"/> -</enum> - -<enum name="a7xx_debugbus_id"> - <value value="1" name="A7XX_DBGBUS_CP_0_0"/> - <value value="2" name="A7XX_DBGBUS_CP_0_1"/> - <value value="3" name="A7XX_DBGBUS_RBBM"/> - <value value="5" name="A7XX_DBGBUS_GBIF_GX"/> - <value value="6" name="A7XX_DBGBUS_GBIF_CX"/> - <value value="7" name="A7XX_DBGBUS_HLSQ"/> - <value value="9" name="A7XX_DBGBUS_UCHE_0"/> - <value value="10" name="A7XX_DBGBUS_UCHE_1"/> - <value value="13" name="A7XX_DBGBUS_TESS_BR"/> - <value value="14" name="A7XX_DBGBUS_TESS_BV"/> - <value value="17" name="A7XX_DBGBUS_PC_BR"/> - <value value="18" name="A7XX_DBGBUS_PC_BV"/> - <value value="21" name="A7XX_DBGBUS_VFDP_BR"/> - <value value="22" name="A7XX_DBGBUS_VFDP_BV"/> - <value value="25" name="A7XX_DBGBUS_VPC_BR"/> - <value value="26" name="A7XX_DBGBUS_VPC_BV"/> - <value value="29" name="A7XX_DBGBUS_TSE_BR"/> - <value value="30" name="A7XX_DBGBUS_TSE_BV"/> - <value value="33" name="A7XX_DBGBUS_RAS_BR"/> - <value value="34" name="A7XX_DBGBUS_RAS_BV"/> - <value value="37" name="A7XX_DBGBUS_VSC"/> - <value value="39" name="A7XX_DBGBUS_COM_0"/> - <value value="43" name="A7XX_DBGBUS_LRZ_BR"/> - <value value="44" name="A7XX_DBGBUS_LRZ_BV"/> - <value value="47" name="A7XX_DBGBUS_UFC_0"/> - <value value="48" name="A7XX_DBGBUS_UFC_1"/> - <value value="55" name="A7XX_DBGBUS_GMU_GX"/> - <value value="59" name="A7XX_DBGBUS_DBGC"/> - <value value="60" name="A7XX_DBGBUS_CX"/> - <value value="61" name="A7XX_DBGBUS_GMU_CX"/> - <value value="62" name="A7XX_DBGBUS_GPC_BR"/> - <value value="63" name="A7XX_DBGBUS_GPC_BV"/> - <value value="66" name="A7XX_DBGBUS_LARC"/> - <value value="68" name="A7XX_DBGBUS_HLSQ_SPTP"/> - <value value="70" name="A7XX_DBGBUS_RB_0"/> - <value value="71" name="A7XX_DBGBUS_RB_1"/> - <value value="72" name="A7XX_DBGBUS_RB_2"/> - <value value="73" name="A7XX_DBGBUS_RB_3"/> - <value value="74" name="A7XX_DBGBUS_RB_4"/> - <value value="75" name="A7XX_DBGBUS_RB_5"/> - <value value="102" name="A7XX_DBGBUS_UCHE_WRAPPER"/> - <value value="106" name="A7XX_DBGBUS_CCU_0"/> - <value value="107" name="A7XX_DBGBUS_CCU_1"/> - <value value="108" name="A7XX_DBGBUS_CCU_2"/> - <value value="109" name="A7XX_DBGBUS_CCU_3"/> - <value value="110" name="A7XX_DBGBUS_CCU_4"/> - <value value="111" name="A7XX_DBGBUS_CCU_5"/> - <value value="138" name="A7XX_DBGBUS_VFD_BR_0"/> - <value value="139" name="A7XX_DBGBUS_VFD_BR_1"/> - <value value="140" name="A7XX_DBGBUS_VFD_BR_2"/> - <value value="141" name="A7XX_DBGBUS_VFD_BR_3"/> - <value value="142" name="A7XX_DBGBUS_VFD_BR_4"/> - <value value="143" name="A7XX_DBGBUS_VFD_BR_5"/> - <value value="144" name="A7XX_DBGBUS_VFD_BR_6"/> - <value value="145" name="A7XX_DBGBUS_VFD_BR_7"/> - <value value="202" name="A7XX_DBGBUS_VFD_BV_0"/> - <value value="203" name="A7XX_DBGBUS_VFD_BV_1"/> - <value value="204" name="A7XX_DBGBUS_VFD_BV_2"/> - <value value="205" name="A7XX_DBGBUS_VFD_BV_3"/> - <value value="234" name="A7XX_DBGBUS_USP_0"/> - <value value="235" name="A7XX_DBGBUS_USP_1"/> - <value value="236" name="A7XX_DBGBUS_USP_2"/> - <value value="237" name="A7XX_DBGBUS_USP_3"/> - <value value="238" name="A7XX_DBGBUS_USP_4"/> - <value value="239" name="A7XX_DBGBUS_USP_5"/> - <value value="266" name="A7XX_DBGBUS_TP_0"/> - <value value="267" name="A7XX_DBGBUS_TP_1"/> - <value value="268" name="A7XX_DBGBUS_TP_2"/> - <value value="269" name="A7XX_DBGBUS_TP_3"/> - <value value="270" name="A7XX_DBGBUS_TP_4"/> - <value value="271" name="A7XX_DBGBUS_TP_5"/> - <value value="272" name="A7XX_DBGBUS_TP_6"/> - <value value="273" name="A7XX_DBGBUS_TP_7"/> - <value value="274" name="A7XX_DBGBUS_TP_8"/> - <value value="275" name="A7XX_DBGBUS_TP_9"/> - <value value="276" name="A7XX_DBGBUS_TP_10"/> - <value value="277" name="A7XX_DBGBUS_TP_11"/> - <value value="330" name="A7XX_DBGBUS_USPTP_0"/> - <value value="331" name="A7XX_DBGBUS_USPTP_1"/> - <value value="332" name="A7XX_DBGBUS_USPTP_2"/> - <value value="333" name="A7XX_DBGBUS_USPTP_3"/> - <value value="334" name="A7XX_DBGBUS_USPTP_4"/> - <value value="335" name="A7XX_DBGBUS_USPTP_5"/> - <value value="336" name="A7XX_DBGBUS_USPTP_6"/> - <value value="337" name="A7XX_DBGBUS_USPTP_7"/> - <value value="338" name="A7XX_DBGBUS_USPTP_8"/> - <value value="339" name="A7XX_DBGBUS_USPTP_9"/> - <value value="340" name="A7XX_DBGBUS_USPTP_10"/> - <value value="341" name="A7XX_DBGBUS_USPTP_11"/> - <value value="396" name="A7XX_DBGBUS_CCHE_0"/> - <value value="397" name="A7XX_DBGBUS_CCHE_1"/> - <value value="398" name="A7XX_DBGBUS_CCHE_2"/> - <value value="408" name="A7XX_DBGBUS_VPC_DSTR_0"/> - <value value="409" name="A7XX_DBGBUS_VPC_DSTR_1"/> - <value value="410" name="A7XX_DBGBUS_VPC_DSTR_2"/> - <value value="411" name="A7XX_DBGBUS_HLSQ_DP_STR_0"/> - <value value="412" name="A7XX_DBGBUS_HLSQ_DP_STR_1"/> - <value value="413" name="A7XX_DBGBUS_HLSQ_DP_STR_2"/> - <value value="414" name="A7XX_DBGBUS_HLSQ_DP_STR_3"/> - <value value="415" name="A7XX_DBGBUS_HLSQ_DP_STR_4"/> - <value value="416" name="A7XX_DBGBUS_HLSQ_DP_STR_5"/> - <value value="443" name="A7XX_DBGBUS_UFC_DSTR_0"/> - <value value="444" name="A7XX_DBGBUS_UFC_DSTR_1"/> - <value value="445" name="A7XX_DBGBUS_UFC_DSTR_2"/> - <value value="446" name="A7XX_DBGBUS_CGC_SUBCORE"/> - <value value="447" name="A7XX_DBGBUS_CGC_CORE"/> -</enum> - -<enum name="a6xx_cp_perfcounter_select"> - <value value="0" name="PERF_CP_ALWAYS_COUNT"/> - <value value="1" name="PERF_CP_BUSY_GFX_CORE_IDLE"/> - <value value="2" name="PERF_CP_BUSY_CYCLES"/> - <value value="3" name="PERF_CP_NUM_PREEMPTIONS"/> - <value value="4" name="PERF_CP_PREEMPTION_REACTION_DELAY"/> - <value value="5" name="PERF_CP_PREEMPTION_SWITCH_OUT_TIME"/> - <value value="6" name="PERF_CP_PREEMPTION_SWITCH_IN_TIME"/> - <value value="7" name="PERF_CP_DEAD_DRAWS_IN_BIN_RENDER"/> - <value value="8" name="PERF_CP_PREDICATED_DRAWS_KILLED"/> - <value value="9" name="PERF_CP_MODE_SWITCH"/> - <value value="10" name="PERF_CP_ZPASS_DONE"/> - <value value="11" name="PERF_CP_CONTEXT_DONE"/> - <value value="12" name="PERF_CP_CACHE_FLUSH"/> - <value value="13" name="PERF_CP_LONG_PREEMPTIONS"/> - <value value="14" name="PERF_CP_SQE_I_CACHE_STARVE"/> - <value value="15" name="PERF_CP_SQE_IDLE"/> - <value value="16" name="PERF_CP_SQE_PM4_STARVE_RB_IB"/> - <value value="17" name="PERF_CP_SQE_PM4_STARVE_SDS"/> - <value value="18" name="PERF_CP_SQE_MRB_STARVE"/> - <value value="19" name="PERF_CP_SQE_RRB_STARVE"/> - <value value="20" name="PERF_CP_SQE_VSD_STARVE"/> - <value value="21" name="PERF_CP_VSD_DECODE_STARVE"/> - <value value="22" name="PERF_CP_SQE_PIPE_OUT_STALL"/> - <value value="23" name="PERF_CP_SQE_SYNC_STALL"/> - <value value="24" name="PERF_CP_SQE_PM4_WFI_STALL"/> - <value value="25" name="PERF_CP_SQE_SYS_WFI_STALL"/> - <value value="26" name="PERF_CP_SQE_T4_EXEC"/> - <value value="27" name="PERF_CP_SQE_LOAD_STATE_EXEC"/> - <value value="28" name="PERF_CP_SQE_SAVE_SDS_STATE"/> - <value value="29" name="PERF_CP_SQE_DRAW_EXEC"/> - <value value="30" name="PERF_CP_SQE_CTXT_REG_BUNCH_EXEC"/> - <value value="31" name="PERF_CP_SQE_EXEC_PROFILED"/> - <value value="32" name="PERF_CP_MEMORY_POOL_EMPTY"/> - <value value="33" name="PERF_CP_MEMORY_POOL_SYNC_STALL"/> - <value value="34" name="PERF_CP_MEMORY_POOL_ABOVE_THRESH"/> - <value value="35" name="PERF_CP_AHB_WR_STALL_PRE_DRAWS"/> - <value value="36" name="PERF_CP_AHB_STALL_SQE_GMU"/> - <value value="37" name="PERF_CP_AHB_STALL_SQE_WR_OTHER"/> - <value value="38" name="PERF_CP_AHB_STALL_SQE_RD_OTHER"/> - <value value="39" name="PERF_CP_CLUSTER0_EMPTY"/> - <value value="40" name="PERF_CP_CLUSTER1_EMPTY"/> - <value value="41" name="PERF_CP_CLUSTER2_EMPTY"/> - <value value="42" name="PERF_CP_CLUSTER3_EMPTY"/> - <value value="43" name="PERF_CP_CLUSTER4_EMPTY"/> - <value value="44" name="PERF_CP_CLUSTER5_EMPTY"/> - <value value="45" name="PERF_CP_PM4_DATA"/> - <value value="46" name="PERF_CP_PM4_HEADERS"/> - <value value="47" name="PERF_CP_VBIF_READ_BEATS"/> - <value value="48" name="PERF_CP_VBIF_WRITE_BEATS"/> - <value value="49" name="PERF_CP_SQE_INSTR_COUNTER"/> -</enum> - -<enum name="a6xx_rbbm_perfcounter_select"> - <value value="0" name="PERF_RBBM_ALWAYS_COUNT"/> - <value value="1" name="PERF_RBBM_ALWAYS_ON"/> - <value value="2" name="PERF_RBBM_TSE_BUSY"/> - <value value="3" name="PERF_RBBM_RAS_BUSY"/> - <value value="4" name="PERF_RBBM_PC_DCALL_BUSY"/> - <value value="5" name="PERF_RBBM_PC_VSD_BUSY"/> - <value value="6" name="PERF_RBBM_STATUS_MASKED"/> - <value value="7" name="PERF_RBBM_COM_BUSY"/> - <value value="8" name="PERF_RBBM_DCOM_BUSY"/> - <value value="9" name="PERF_RBBM_VBIF_BUSY"/> - <value value="10" name="PERF_RBBM_VSC_BUSY"/> - <value value="11" name="PERF_RBBM_TESS_BUSY"/> - <value value="12" name="PERF_RBBM_UCHE_BUSY"/> - <value value="13" name="PERF_RBBM_HLSQ_BUSY"/> -</enum> - -<enum name="a6xx_pc_perfcounter_select"> - <value value="0" name="PERF_PC_BUSY_CYCLES"/> - <value value="1" name="PERF_PC_WORKING_CYCLES"/> - <value value="2" name="PERF_PC_STALL_CYCLES_VFD"/> - <value value="3" name="PERF_PC_STALL_CYCLES_TSE"/> - <value value="4" name="PERF_PC_STALL_CYCLES_VPC"/> - <value value="5" name="PERF_PC_STALL_CYCLES_UCHE"/> - <value value="6" name="PERF_PC_STALL_CYCLES_TESS"/> - <value value="7" name="PERF_PC_STALL_CYCLES_TSE_ONLY"/> - <value value="8" name="PERF_PC_STALL_CYCLES_VPC_ONLY"/> - <value value="9" name="PERF_PC_PASS1_TF_STALL_CYCLES"/> - <value value="10" name="PERF_PC_STARVE_CYCLES_FOR_INDEX"/> - <value value="11" name="PERF_PC_STARVE_CYCLES_FOR_TESS_FACTOR"/> - <value value="12" name="PERF_PC_STARVE_CYCLES_FOR_VIZ_STREAM"/> - <value value="13" name="PERF_PC_STARVE_CYCLES_FOR_POSITION"/> - <value value="14" name="PERF_PC_STARVE_CYCLES_DI"/> - <value value="15" name="PERF_PC_VIS_STREAMS_LOADED"/> - <value value="16" name="PERF_PC_INSTANCES"/> - <value value="17" name="PERF_PC_VPC_PRIMITIVES"/> - <value value="18" name="PERF_PC_DEAD_PRIM"/> - <value value="19" name="PERF_PC_LIVE_PRIM"/> - <value value="20" name="PERF_PC_VERTEX_HITS"/> - <value value="21" name="PERF_PC_IA_VERTICES"/> - <value value="22" name="PERF_PC_IA_PRIMITIVES"/> - <value value="23" name="PERF_PC_GS_PRIMITIVES"/> - <value value="24" name="PERF_PC_HS_INVOCATIONS"/> - <value value="25" name="PERF_PC_DS_INVOCATIONS"/> - <value value="26" name="PERF_PC_VS_INVOCATIONS"/> - <value value="27" name="PERF_PC_GS_INVOCATIONS"/> - <value value="28" name="PERF_PC_DS_PRIMITIVES"/> - <value value="29" name="PERF_PC_VPC_POS_DATA_TRANSACTION"/> - <value value="30" name="PERF_PC_3D_DRAWCALLS"/> - <value value="31" name="PERF_PC_2D_DRAWCALLS"/> - <value value="32" name="PERF_PC_NON_DRAWCALL_GLOBAL_EVENTS"/> - <value value="33" name="PERF_TESS_BUSY_CYCLES"/> - <value value="34" name="PERF_TESS_WORKING_CYCLES"/> - <value value="35" name="PERF_TESS_STALL_CYCLES_PC"/> - <value value="36" name="PERF_TESS_STARVE_CYCLES_PC"/> - <value value="37" name="PERF_PC_TSE_TRANSACTION"/> - <value value="38" name="PERF_PC_TSE_VERTEX"/> - <value value="39" name="PERF_PC_TESS_PC_UV_TRANS"/> - <value value="40" name="PERF_PC_TESS_PC_UV_PATCHES"/> - <value value="41" name="PERF_PC_TESS_FACTOR_TRANS"/> -</enum> - -<enum name="a6xx_vfd_perfcounter_select"> - <value value="0" name="PERF_VFD_BUSY_CYCLES"/> - <value value="1" name="PERF_VFD_STALL_CYCLES_UCHE"/> - <value value="2" name="PERF_VFD_STALL_CYCLES_VPC_ALLOC"/> - <value value="3" name="PERF_VFD_STALL_CYCLES_SP_INFO"/> - <value value="4" name="PERF_VFD_STALL_CYCLES_SP_ATTR"/> - <value value="5" name="PERF_VFD_STARVE_CYCLES_UCHE"/> - <value value="6" name="PERF_VFD_RBUFFER_FULL"/> - <value value="7" name="PERF_VFD_ATTR_INFO_FIFO_FULL"/> - <value value="8" name="PERF_VFD_DECODED_ATTRIBUTE_BYTES"/> - <value value="9" name="PERF_VFD_NUM_ATTRIBUTES"/> - <value value="10" name="PERF_VFD_UPPER_SHADER_FIBERS"/> - <value value="11" name="PERF_VFD_LOWER_SHADER_FIBERS"/> - <value value="12" name="PERF_VFD_MODE_0_FIBERS"/> - <value value="13" name="PERF_VFD_MODE_1_FIBERS"/> - <value value="14" name="PERF_VFD_MODE_2_FIBERS"/> - <value value="15" name="PERF_VFD_MODE_3_FIBERS"/> - <value value="16" name="PERF_VFD_MODE_4_FIBERS"/> - <value value="17" name="PERF_VFD_TOTAL_VERTICES"/> - <value value="18" name="PERF_VFDP_STALL_CYCLES_VFD"/> - <value value="19" name="PERF_VFDP_STALL_CYCLES_VFD_INDEX"/> - <value value="20" name="PERF_VFDP_STALL_CYCLES_VFD_PROG"/> - <value value="21" name="PERF_VFDP_STARVE_CYCLES_PC"/> - <value value="22" name="PERF_VFDP_VS_STAGE_WAVES"/> -</enum> - -<enum name="a6xx_hlsq_perfcounter_select"> - <value value="0" name="PERF_HLSQ_BUSY_CYCLES"/> - <value value="1" name="PERF_HLSQ_STALL_CYCLES_UCHE"/> - <value value="2" name="PERF_HLSQ_STALL_CYCLES_SP_STATE"/> - <value value="3" name="PERF_HLSQ_STALL_CYCLES_SP_FS_STAGE"/> - <value value="4" name="PERF_HLSQ_UCHE_LATENCY_CYCLES"/> - <value value="5" name="PERF_HLSQ_UCHE_LATENCY_COUNT"/> - <value value="6" name="PERF_HLSQ_FS_STAGE_1X_WAVES"/> - <value value="7" name="PERF_HLSQ_FS_STAGE_2X_WAVES"/> - <value value="8" name="PERF_HLSQ_QUADS"/> - <value value="9" name="PERF_HLSQ_CS_INVOCATIONS"/> - <value value="10" name="PERF_HLSQ_COMPUTE_DRAWCALLS"/> - <value value="11" name="PERF_HLSQ_FS_DATA_WAIT_PROGRAMMING"/> - <value value="12" name="PERF_HLSQ_DUAL_FS_PROG_ACTIVE"/> - <value value="13" name="PERF_HLSQ_DUAL_VS_PROG_ACTIVE"/> - <value value="14" name="PERF_HLSQ_FS_BATCH_COUNT_ZERO"/> - <value value="15" name="PERF_HLSQ_VS_BATCH_COUNT_ZERO"/> - <value value="16" name="PERF_HLSQ_WAVE_PENDING_NO_QUAD"/> - <value value="17" name="PERF_HLSQ_WAVE_PENDING_NO_PRIM_BASE"/> - <value value="18" name="PERF_HLSQ_STALL_CYCLES_VPC"/> - <value value="19" name="PERF_HLSQ_PIXELS"/> - <value value="20" name="PERF_HLSQ_DRAW_MODE_SWITCH_VSFS_SYNC"/> -</enum> - -<enum name="a6xx_vpc_perfcounter_select"> - <value value="0" name="PERF_VPC_BUSY_CYCLES"/> - <value value="1" name="PERF_VPC_WORKING_CYCLES"/> - <value value="2" name="PERF_VPC_STALL_CYCLES_UCHE"/> - <value value="3" name="PERF_VPC_STALL_CYCLES_VFD_WACK"/> - <value value="4" name="PERF_VPC_STALL_CYCLES_HLSQ_PRIM_ALLOC"/> - <value value="5" name="PERF_VPC_STALL_CYCLES_PC"/> - <value value="6" name="PERF_VPC_STALL_CYCLES_SP_LM"/> - <value value="7" name="PERF_VPC_STARVE_CYCLES_SP"/> - <value value="8" name="PERF_VPC_STARVE_CYCLES_LRZ"/> - <value value="9" name="PERF_VPC_PC_PRIMITIVES"/> - <value value="10" name="PERF_VPC_SP_COMPONENTS"/> - <value value="11" name="PERF_VPC_STALL_CYCLES_VPCRAM_POS"/> - <value value="12" name="PERF_VPC_LRZ_ASSIGN_PRIMITIVES"/> - <value value="13" name="PERF_VPC_RB_VISIBLE_PRIMITIVES"/> - <value value="14" name="PERF_VPC_LM_TRANSACTION"/> - <value value="15" name="PERF_VPC_STREAMOUT_TRANSACTION"/> - <value value="16" name="PERF_VPC_VS_BUSY_CYCLES"/> - <value value="17" name="PERF_VPC_PS_BUSY_CYCLES"/> - <value value="18" name="PERF_VPC_VS_WORKING_CYCLES"/> - <value value="19" name="PERF_VPC_PS_WORKING_CYCLES"/> - <value value="20" name="PERF_VPC_STARVE_CYCLES_RB"/> - <value value="21" name="PERF_VPC_NUM_VPCRAM_READ_POS"/> - <value value="22" name="PERF_VPC_WIT_FULL_CYCLES"/> - <value value="23" name="PERF_VPC_VPCRAM_FULL_CYCLES"/> - <value value="24" name="PERF_VPC_LM_FULL_WAIT_FOR_INTP_END"/> - <value value="25" name="PERF_VPC_NUM_VPCRAM_WRITE"/> - <value value="26" name="PERF_VPC_NUM_VPCRAM_READ_SO"/> - <value value="27" name="PERF_VPC_NUM_ATTR_REQ_LM"/> -</enum> - -<enum name="a6xx_tse_perfcounter_select"> - <value value="0" name="PERF_TSE_BUSY_CYCLES"/> - <value value="1" name="PERF_TSE_CLIPPING_CYCLES"/> - <value value="2" name="PERF_TSE_STALL_CYCLES_RAS"/> - <value value="3" name="PERF_TSE_STALL_CYCLES_LRZ_BARYPLANE"/> - <value value="4" name="PERF_TSE_STALL_CYCLES_LRZ_ZPLANE"/> - <value value="5" name="PERF_TSE_STARVE_CYCLES_PC"/> - <value value="6" name="PERF_TSE_INPUT_PRIM"/> - <value value="7" name="PERF_TSE_INPUT_NULL_PRIM"/> - <value value="8" name="PERF_TSE_TRIVAL_REJ_PRIM"/> - <value value="9" name="PERF_TSE_CLIPPED_PRIM"/> - <value value="10" name="PERF_TSE_ZERO_AREA_PRIM"/> - <value value="11" name="PERF_TSE_FACENESS_CULLED_PRIM"/> - <value value="12" name="PERF_TSE_ZERO_PIXEL_PRIM"/> - <value value="13" name="PERF_TSE_OUTPUT_NULL_PRIM"/> - <value value="14" name="PERF_TSE_OUTPUT_VISIBLE_PRIM"/> - <value value="15" name="PERF_TSE_CINVOCATION"/> - <value value="16" name="PERF_TSE_CPRIMITIVES"/> - <value value="17" name="PERF_TSE_2D_INPUT_PRIM"/> - <value value="18" name="PERF_TSE_2D_ALIVE_CYCLES"/> - <value value="19" name="PERF_TSE_CLIP_PLANES"/> -</enum> - -<enum name="a6xx_ras_perfcounter_select"> - <value value="0" name="PERF_RAS_BUSY_CYCLES"/> - <value value="1" name="PERF_RAS_SUPERTILE_ACTIVE_CYCLES"/> - <value value="2" name="PERF_RAS_STALL_CYCLES_LRZ"/> - <value value="3" name="PERF_RAS_STARVE_CYCLES_TSE"/> - <value value="4" name="PERF_RAS_SUPER_TILES"/> - <value value="5" name="PERF_RAS_8X4_TILES"/> - <value value="6" name="PERF_RAS_MASKGEN_ACTIVE"/> - <value value="7" name="PERF_RAS_FULLY_COVERED_SUPER_TILES"/> - <value value="8" name="PERF_RAS_FULLY_COVERED_8X4_TILES"/> - <value value="9" name="PERF_RAS_PRIM_KILLED_INVISILBE"/> - <value value="10" name="PERF_RAS_SUPERTILE_GEN_ACTIVE_CYCLES"/> - <value value="11" name="PERF_RAS_LRZ_INTF_WORKING_CYCLES"/> - <value value="12" name="PERF_RAS_BLOCKS"/> -</enum> - -<enum name="a6xx_uche_perfcounter_select"> - <value value="0" name="PERF_UCHE_BUSY_CYCLES"/> - <value value="1" name="PERF_UCHE_STALL_CYCLES_ARBITER"/> - <value value="2" name="PERF_UCHE_VBIF_LATENCY_CYCLES"/> - <value value="3" name="PERF_UCHE_VBIF_LATENCY_SAMPLES"/> - <value value="4" name="PERF_UCHE_VBIF_READ_BEATS_TP"/> - <value value="5" name="PERF_UCHE_VBIF_READ_BEATS_VFD"/> - <value value="6" name="PERF_UCHE_VBIF_READ_BEATS_HLSQ"/> - <value value="7" name="PERF_UCHE_VBIF_READ_BEATS_LRZ"/> - <value value="8" name="PERF_UCHE_VBIF_READ_BEATS_SP"/> - <value value="9" name="PERF_UCHE_READ_REQUESTS_TP"/> - <value value="10" name="PERF_UCHE_READ_REQUESTS_VFD"/> - <value value="11" name="PERF_UCHE_READ_REQUESTS_HLSQ"/> - <value value="12" name="PERF_UCHE_READ_REQUESTS_LRZ"/> - <value value="13" name="PERF_UCHE_READ_REQUESTS_SP"/> - <value value="14" name="PERF_UCHE_WRITE_REQUESTS_LRZ"/> - <value value="15" name="PERF_UCHE_WRITE_REQUESTS_SP"/> - <value value="16" name="PERF_UCHE_WRITE_REQUESTS_VPC"/> - <value value="17" name="PERF_UCHE_WRITE_REQUESTS_VSC"/> - <value value="18" name="PERF_UCHE_EVICTS"/> - <value value="19" name="PERF_UCHE_BANK_REQ0"/> - <value value="20" name="PERF_UCHE_BANK_REQ1"/> - <value value="21" name="PERF_UCHE_BANK_REQ2"/> - <value value="22" name="PERF_UCHE_BANK_REQ3"/> - <value value="23" name="PERF_UCHE_BANK_REQ4"/> - <value value="24" name="PERF_UCHE_BANK_REQ5"/> - <value value="25" name="PERF_UCHE_BANK_REQ6"/> - <value value="26" name="PERF_UCHE_BANK_REQ7"/> - <value value="27" name="PERF_UCHE_VBIF_READ_BEATS_CH0"/> - <value value="28" name="PERF_UCHE_VBIF_READ_BEATS_CH1"/> - <value value="29" name="PERF_UCHE_GMEM_READ_BEATS"/> - <value value="30" name="PERF_UCHE_TPH_REF_FULL"/> - <value value="31" name="PERF_UCHE_TPH_VICTIM_FULL"/> - <value value="32" name="PERF_UCHE_TPH_EXT_FULL"/> - <value value="33" name="PERF_UCHE_VBIF_STALL_WRITE_DATA"/> - <value value="34" name="PERF_UCHE_DCMP_LATENCY_SAMPLES"/> - <value value="35" name="PERF_UCHE_DCMP_LATENCY_CYCLES"/> - <value value="36" name="PERF_UCHE_VBIF_READ_BEATS_PC"/> - <value value="37" name="PERF_UCHE_READ_REQUESTS_PC"/> - <value value="38" name="PERF_UCHE_RAM_READ_REQ"/> - <value value="39" name="PERF_UCHE_RAM_WRITE_REQ"/> -</enum> - -<enum name="a6xx_tp_perfcounter_select"> - <value value="0" name="PERF_TP_BUSY_CYCLES"/> - <value value="1" name="PERF_TP_STALL_CYCLES_UCHE"/> - <value value="2" name="PERF_TP_LATENCY_CYCLES"/> - <value value="3" name="PERF_TP_LATENCY_TRANS"/> - <value value="4" name="PERF_TP_FLAG_CACHE_REQUEST_SAMPLES"/> - <value value="5" name="PERF_TP_FLAG_CACHE_REQUEST_LATENCY"/> - <value value="6" name="PERF_TP_L1_CACHELINE_REQUESTS"/> - <value value="7" name="PERF_TP_L1_CACHELINE_MISSES"/> - <value value="8" name="PERF_TP_SP_TP_TRANS"/> - <value value="9" name="PERF_TP_TP_SP_TRANS"/> - <value value="10" name="PERF_TP_OUTPUT_PIXELS"/> - <value value="11" name="PERF_TP_FILTER_WORKLOAD_16BIT"/> - <value value="12" name="PERF_TP_FILTER_WORKLOAD_32BIT"/> - <value value="13" name="PERF_TP_QUADS_RECEIVED"/> - <value value="14" name="PERF_TP_QUADS_OFFSET"/> - <value value="15" name="PERF_TP_QUADS_SHADOW"/> - <value value="16" name="PERF_TP_QUADS_ARRAY"/> - <value value="17" name="PERF_TP_QUADS_GRADIENT"/> - <value value="18" name="PERF_TP_QUADS_1D"/> - <value value="19" name="PERF_TP_QUADS_2D"/> - <value value="20" name="PERF_TP_QUADS_BUFFER"/> - <value value="21" name="PERF_TP_QUADS_3D"/> - <value value="22" name="PERF_TP_QUADS_CUBE"/> - <value value="23" name="PERF_TP_DIVERGENT_QUADS_RECEIVED"/> - <value value="24" name="PERF_TP_PRT_NON_RESIDENT_EVENTS"/> - <value value="25" name="PERF_TP_OUTPUT_PIXELS_POINT"/> - <value value="26" name="PERF_TP_OUTPUT_PIXELS_BILINEAR"/> - <value value="27" name="PERF_TP_OUTPUT_PIXELS_MIP"/> - <value value="28" name="PERF_TP_OUTPUT_PIXELS_ANISO"/> - <value value="29" name="PERF_TP_OUTPUT_PIXELS_ZERO_LOD"/> - <value value="30" name="PERF_TP_FLAG_CACHE_REQUESTS"/> - <value value="31" name="PERF_TP_FLAG_CACHE_MISSES"/> - <value value="32" name="PERF_TP_L1_5_L2_REQUESTS"/> - <value value="33" name="PERF_TP_2D_OUTPUT_PIXELS"/> - <value value="34" name="PERF_TP_2D_OUTPUT_PIXELS_POINT"/> - <value value="35" name="PERF_TP_2D_OUTPUT_PIXELS_BILINEAR"/> - <value value="36" name="PERF_TP_2D_FILTER_WORKLOAD_16BIT"/> - <value value="37" name="PERF_TP_2D_FILTER_WORKLOAD_32BIT"/> - <value value="38" name="PERF_TP_TPA2TPC_TRANS"/> - <value value="39" name="PERF_TP_L1_MISSES_ASTC_1TILE"/> - <value value="40" name="PERF_TP_L1_MISSES_ASTC_2TILE"/> - <value value="41" name="PERF_TP_L1_MISSES_ASTC_4TILE"/> - <value value="42" name="PERF_TP_L1_5_L2_COMPRESS_REQS"/> - <value value="43" name="PERF_TP_L1_5_L2_COMPRESS_MISS"/> - <value value="44" name="PERF_TP_L1_BANK_CONFLICT"/> - <value value="45" name="PERF_TP_L1_5_MISS_LATENCY_CYCLES"/> - <value value="46" name="PERF_TP_L1_5_MISS_LATENCY_TRANS"/> - <value value="47" name="PERF_TP_QUADS_CONSTANT_MULTIPLIED"/> - <value value="48" name="PERF_TP_FRONTEND_WORKING_CYCLES"/> - <value value="49" name="PERF_TP_L1_TAG_WORKING_CYCLES"/> - <value value="50" name="PERF_TP_L1_DATA_WRITE_WORKING_CYCLES"/> - <value value="51" name="PERF_TP_PRE_L1_DECOM_WORKING_CYCLES"/> - <value value="52" name="PERF_TP_BACKEND_WORKING_CYCLES"/> - <value value="53" name="PERF_TP_FLAG_CACHE_WORKING_CYCLES"/> - <value value="54" name="PERF_TP_L1_5_CACHE_WORKING_CYCLES"/> - <value value="55" name="PERF_TP_STARVE_CYCLES_SP"/> - <value value="56" name="PERF_TP_STARVE_CYCLES_UCHE"/> -</enum> - -<enum name="a6xx_sp_perfcounter_select"> - <value value="0" name="PERF_SP_BUSY_CYCLES"/> - <value value="1" name="PERF_SP_ALU_WORKING_CYCLES"/> - <value value="2" name="PERF_SP_EFU_WORKING_CYCLES"/> - <value value="3" name="PERF_SP_STALL_CYCLES_VPC"/> - <value value="4" name="PERF_SP_STALL_CYCLES_TP"/> - <value value="5" name="PERF_SP_STALL_CYCLES_UCHE"/> - <value value="6" name="PERF_SP_STALL_CYCLES_RB"/> - <value value="7" name="PERF_SP_NON_EXECUTION_CYCLES"/> - <value value="8" name="PERF_SP_WAVE_CONTEXTS"/> - <value value="9" name="PERF_SP_WAVE_CONTEXT_CYCLES"/> - <value value="10" name="PERF_SP_FS_STAGE_WAVE_CYCLES"/> - <value value="11" name="PERF_SP_FS_STAGE_WAVE_SAMPLES"/> - <value value="12" name="PERF_SP_VS_STAGE_WAVE_CYCLES"/> - <value value="13" name="PERF_SP_VS_STAGE_WAVE_SAMPLES"/> - <value value="14" name="PERF_SP_FS_STAGE_DURATION_CYCLES"/> - <value value="15" name="PERF_SP_VS_STAGE_DURATION_CYCLES"/> - <value value="16" name="PERF_SP_WAVE_CTRL_CYCLES"/> - <value value="17" name="PERF_SP_WAVE_LOAD_CYCLES"/> - <value value="18" name="PERF_SP_WAVE_EMIT_CYCLES"/> - <value value="19" name="PERF_SP_WAVE_NOP_CYCLES"/> - <value value="20" name="PERF_SP_WAVE_WAIT_CYCLES"/> - <value value="21" name="PERF_SP_WAVE_FETCH_CYCLES"/> - <value value="22" name="PERF_SP_WAVE_IDLE_CYCLES"/> - <value value="23" name="PERF_SP_WAVE_END_CYCLES"/> - <value value="24" name="PERF_SP_WAVE_LONG_SYNC_CYCLES"/> - <value value="25" name="PERF_SP_WAVE_SHORT_SYNC_CYCLES"/> - <value value="26" name="PERF_SP_WAVE_JOIN_CYCLES"/> - <value value="27" name="PERF_SP_LM_LOAD_INSTRUCTIONS"/> - <value value="28" name="PERF_SP_LM_STORE_INSTRUCTIONS"/> - <value value="29" name="PERF_SP_LM_ATOMICS"/> - <value value="30" name="PERF_SP_GM_LOAD_INSTRUCTIONS"/> - <value value="31" name="PERF_SP_GM_STORE_INSTRUCTIONS"/> - <value value="32" name="PERF_SP_GM_ATOMICS"/> - <value value="33" name="PERF_SP_VS_STAGE_TEX_INSTRUCTIONS"/> - <value value="34" name="PERF_SP_VS_STAGE_EFU_INSTRUCTIONS"/> - <value value="35" name="PERF_SP_VS_STAGE_FULL_ALU_INSTRUCTIONS"/> - <value value="36" name="PERF_SP_VS_STAGE_HALF_ALU_INSTRUCTIONS"/> - <value value="37" name="PERF_SP_FS_STAGE_TEX_INSTRUCTIONS"/> - <value value="38" name="PERF_SP_FS_STAGE_CFLOW_INSTRUCTIONS"/> - <value value="39" name="PERF_SP_FS_STAGE_EFU_INSTRUCTIONS"/> - <value value="40" name="PERF_SP_FS_STAGE_FULL_ALU_INSTRUCTIONS"/> - <value value="41" name="PERF_SP_FS_STAGE_HALF_ALU_INSTRUCTIONS"/> - <value value="42" name="PERF_SP_FS_STAGE_BARY_INSTRUCTIONS"/> - <value value="43" name="PERF_SP_VS_INSTRUCTIONS"/> - <value value="44" name="PERF_SP_FS_INSTRUCTIONS"/> - <value value="45" name="PERF_SP_ADDR_LOCK_COUNT"/> - <value value="46" name="PERF_SP_UCHE_READ_TRANS"/> - <value value="47" name="PERF_SP_UCHE_WRITE_TRANS"/> - <value value="48" name="PERF_SP_EXPORT_VPC_TRANS"/> - <value value="49" name="PERF_SP_EXPORT_RB_TRANS"/> - <value value="50" name="PERF_SP_PIXELS_KILLED"/> - <value value="51" name="PERF_SP_ICL1_REQUESTS"/> - <value value="52" name="PERF_SP_ICL1_MISSES"/> - <value value="53" name="PERF_SP_HS_INSTRUCTIONS"/> - <value value="54" name="PERF_SP_DS_INSTRUCTIONS"/> - <value value="55" name="PERF_SP_GS_INSTRUCTIONS"/> - <value value="56" name="PERF_SP_CS_INSTRUCTIONS"/> - <value value="57" name="PERF_SP_GPR_READ"/> - <value value="58" name="PERF_SP_GPR_WRITE"/> - <value value="59" name="PERF_SP_FS_STAGE_HALF_EFU_INSTRUCTIONS"/> - <value value="60" name="PERF_SP_VS_STAGE_HALF_EFU_INSTRUCTIONS"/> - <value value="61" name="PERF_SP_LM_BANK_CONFLICTS"/> - <value value="62" name="PERF_SP_TEX_CONTROL_WORKING_CYCLES"/> - <value value="63" name="PERF_SP_LOAD_CONTROL_WORKING_CYCLES"/> - <value value="64" name="PERF_SP_FLOW_CONTROL_WORKING_CYCLES"/> - <value value="65" name="PERF_SP_LM_WORKING_CYCLES"/> - <value value="66" name="PERF_SP_DISPATCHER_WORKING_CYCLES"/> - <value value="67" name="PERF_SP_SEQUENCER_WORKING_CYCLES"/> - <value value="68" name="PERF_SP_LOW_EFFICIENCY_STARVED_BY_TP"/> - <value value="69" name="PERF_SP_STARVE_CYCLES_HLSQ"/> - <value value="70" name="PERF_SP_NON_EXECUTION_LS_CYCLES"/> - <value value="71" name="PERF_SP_WORKING_EU"/> - <value value="72" name="PERF_SP_ANY_EU_WORKING"/> - <value value="73" name="PERF_SP_WORKING_EU_FS_STAGE"/> - <value value="74" name="PERF_SP_ANY_EU_WORKING_FS_STAGE"/> - <value value="75" name="PERF_SP_WORKING_EU_VS_STAGE"/> - <value value="76" name="PERF_SP_ANY_EU_WORKING_VS_STAGE"/> - <value value="77" name="PERF_SP_WORKING_EU_CS_STAGE"/> - <value value="78" name="PERF_SP_ANY_EU_WORKING_CS_STAGE"/> - <value value="79" name="PERF_SP_GPR_READ_PREFETCH"/> - <value value="80" name="PERF_SP_GPR_READ_CONFLICT"/> - <value value="81" name="PERF_SP_GPR_WRITE_CONFLICT"/> - <value value="82" name="PERF_SP_GM_LOAD_LATENCY_CYCLES"/> - <value value="83" name="PERF_SP_GM_LOAD_LATENCY_SAMPLES"/> - <value value="84" name="PERF_SP_EXECUTABLE_WAVES"/> -</enum> - -<enum name="a6xx_rb_perfcounter_select"> - <value value="0" name="PERF_RB_BUSY_CYCLES"/> - <value value="1" name="PERF_RB_STALL_CYCLES_HLSQ"/> - <value value="2" name="PERF_RB_STALL_CYCLES_FIFO0_FULL"/> - <value value="3" name="PERF_RB_STALL_CYCLES_FIFO1_FULL"/> - <value value="4" name="PERF_RB_STALL_CYCLES_FIFO2_FULL"/> - <value value="5" name="PERF_RB_STARVE_CYCLES_SP"/> - <value value="6" name="PERF_RB_STARVE_CYCLES_LRZ_TILE"/> - <value value="7" name="PERF_RB_STARVE_CYCLES_CCU"/> - <value value="8" name="PERF_RB_STARVE_CYCLES_Z_PLANE"/> - <value value="9" name="PERF_RB_STARVE_CYCLES_BARY_PLANE"/> - <value value="10" name="PERF_RB_Z_WORKLOAD"/> - <value value="11" name="PERF_RB_HLSQ_ACTIVE"/> - <value value="12" name="PERF_RB_Z_READ"/> - <value value="13" name="PERF_RB_Z_WRITE"/> - <value value="14" name="PERF_RB_C_READ"/> - <value value="15" name="PERF_RB_C_WRITE"/> - <value value="16" name="PERF_RB_TOTAL_PASS"/> - <value value="17" name="PERF_RB_Z_PASS"/> - <value value="18" name="PERF_RB_Z_FAIL"/> - <value value="19" name="PERF_RB_S_FAIL"/> - <value value="20" name="PERF_RB_BLENDED_FXP_COMPONENTS"/> - <value value="21" name="PERF_RB_BLENDED_FP16_COMPONENTS"/> - <value value="22" name="PERF_RB_PS_INVOCATIONS"/> - <value value="23" name="PERF_RB_2D_ALIVE_CYCLES"/> - <value value="24" name="PERF_RB_2D_STALL_CYCLES_A2D"/> - <value value="25" name="PERF_RB_2D_STARVE_CYCLES_SRC"/> - <value value="26" name="PERF_RB_2D_STARVE_CYCLES_SP"/> - <value value="27" name="PERF_RB_2D_STARVE_CYCLES_DST"/> - <value value="28" name="PERF_RB_2D_VALID_PIXELS"/> - <value value="29" name="PERF_RB_3D_PIXELS"/> - <value value="30" name="PERF_RB_BLENDER_WORKING_CYCLES"/> - <value value="31" name="PERF_RB_ZPROC_WORKING_CYCLES"/> - <value value="32" name="PERF_RB_CPROC_WORKING_CYCLES"/> - <value value="33" name="PERF_RB_SAMPLER_WORKING_CYCLES"/> - <value value="34" name="PERF_RB_STALL_CYCLES_CCU_COLOR_READ"/> - <value value="35" name="PERF_RB_STALL_CYCLES_CCU_COLOR_WRITE"/> - <value value="36" name="PERF_RB_STALL_CYCLES_CCU_DEPTH_READ"/> - <value value="37" name="PERF_RB_STALL_CYCLES_CCU_DEPTH_WRITE"/> - <value value="38" name="PERF_RB_STALL_CYCLES_VPC"/> - <value value="39" name="PERF_RB_2D_INPUT_TRANS"/> - <value value="40" name="PERF_RB_2D_OUTPUT_RB_DST_TRANS"/> - <value value="41" name="PERF_RB_2D_OUTPUT_RB_SRC_TRANS"/> - <value value="42" name="PERF_RB_BLENDED_FP32_COMPONENTS"/> - <value value="43" name="PERF_RB_COLOR_PIX_TILES"/> - <value value="44" name="PERF_RB_STALL_CYCLES_CCU"/> - <value value="45" name="PERF_RB_EARLY_Z_ARB3_GRANT"/> - <value value="46" name="PERF_RB_LATE_Z_ARB3_GRANT"/> - <value value="47" name="PERF_RB_EARLY_Z_SKIP_GRANT"/> -</enum> - -<enum name="a6xx_vsc_perfcounter_select"> - <value value="0" name="PERF_VSC_BUSY_CYCLES"/> - <value value="1" name="PERF_VSC_WORKING_CYCLES"/> - <value value="2" name="PERF_VSC_STALL_CYCLES_UCHE"/> - <value value="3" name="PERF_VSC_EOT_NUM"/> - <value value="4" name="PERF_VSC_INPUT_TILES"/> -</enum> - -<enum name="a6xx_ccu_perfcounter_select"> - <value value="0" name="PERF_CCU_BUSY_CYCLES"/> - <value value="1" name="PERF_CCU_STALL_CYCLES_RB_DEPTH_RETURN"/> - <value value="2" name="PERF_CCU_STALL_CYCLES_RB_COLOR_RETURN"/> - <value value="3" name="PERF_CCU_STARVE_CYCLES_FLAG_RETURN"/> - <value value="4" name="PERF_CCU_DEPTH_BLOCKS"/> - <value value="5" name="PERF_CCU_COLOR_BLOCKS"/> - <value value="6" name="PERF_CCU_DEPTH_BLOCK_HIT"/> - <value value="7" name="PERF_CCU_COLOR_BLOCK_HIT"/> - <value value="8" name="PERF_CCU_PARTIAL_BLOCK_READ"/> - <value value="9" name="PERF_CCU_GMEM_READ"/> - <value value="10" name="PERF_CCU_GMEM_WRITE"/> - <value value="11" name="PERF_CCU_DEPTH_READ_FLAG0_COUNT"/> - <value value="12" name="PERF_CCU_DEPTH_READ_FLAG1_COUNT"/> - <value value="13" name="PERF_CCU_DEPTH_READ_FLAG2_COUNT"/> - <value value="14" name="PERF_CCU_DEPTH_READ_FLAG3_COUNT"/> - <value value="15" name="PERF_CCU_DEPTH_READ_FLAG4_COUNT"/> - <value value="16" name="PERF_CCU_DEPTH_READ_FLAG5_COUNT"/> - <value value="17" name="PERF_CCU_DEPTH_READ_FLAG6_COUNT"/> - <value value="18" name="PERF_CCU_DEPTH_READ_FLAG8_COUNT"/> - <value value="19" name="PERF_CCU_COLOR_READ_FLAG0_COUNT"/> - <value value="20" name="PERF_CCU_COLOR_READ_FLAG1_COUNT"/> - <value value="21" name="PERF_CCU_COLOR_READ_FLAG2_COUNT"/> - <value value="22" name="PERF_CCU_COLOR_READ_FLAG3_COUNT"/> - <value value="23" name="PERF_CCU_COLOR_READ_FLAG4_COUNT"/> - <value value="24" name="PERF_CCU_COLOR_READ_FLAG5_COUNT"/> - <value value="25" name="PERF_CCU_COLOR_READ_FLAG6_COUNT"/> - <value value="26" name="PERF_CCU_COLOR_READ_FLAG8_COUNT"/> - <value value="27" name="PERF_CCU_2D_RD_REQ"/> - <value value="28" name="PERF_CCU_2D_WR_REQ"/> -</enum> - -<enum name="a6xx_lrz_perfcounter_select"> - <value value="0" name="PERF_LRZ_BUSY_CYCLES"/> - <value value="1" name="PERF_LRZ_STARVE_CYCLES_RAS"/> - <value value="2" name="PERF_LRZ_STALL_CYCLES_RB"/> - <value value="3" name="PERF_LRZ_STALL_CYCLES_VSC"/> - <value value="4" name="PERF_LRZ_STALL_CYCLES_VPC"/> - <value value="5" name="PERF_LRZ_STALL_CYCLES_FLAG_PREFETCH"/> - <value value="6" name="PERF_LRZ_STALL_CYCLES_UCHE"/> - <value value="7" name="PERF_LRZ_LRZ_READ"/> - <value value="8" name="PERF_LRZ_LRZ_WRITE"/> - <value value="9" name="PERF_LRZ_READ_LATENCY"/> - <value value="10" name="PERF_LRZ_MERGE_CACHE_UPDATING"/> - <value value="11" name="PERF_LRZ_PRIM_KILLED_BY_MASKGEN"/> - <value value="12" name="PERF_LRZ_PRIM_KILLED_BY_LRZ"/> - <value value="13" name="PERF_LRZ_VISIBLE_PRIM_AFTER_LRZ"/> - <value value="14" name="PERF_LRZ_FULL_8X8_TILES"/> - <value value="15" name="PERF_LRZ_PARTIAL_8X8_TILES"/> - <value value="16" name="PERF_LRZ_TILE_KILLED"/> - <value value="17" name="PERF_LRZ_TOTAL_PIXEL"/> - <value value="18" name="PERF_LRZ_VISIBLE_PIXEL_AFTER_LRZ"/> - <value value="19" name="PERF_LRZ_FULLY_COVERED_TILES"/> - <value value="20" name="PERF_LRZ_PARTIAL_COVERED_TILES"/> - <value value="21" name="PERF_LRZ_FEEDBACK_ACCEPT"/> - <value value="22" name="PERF_LRZ_FEEDBACK_DISCARD"/> - <value value="23" name="PERF_LRZ_FEEDBACK_STALL"/> - <value value="24" name="PERF_LRZ_STALL_CYCLES_RB_ZPLANE"/> - <value value="25" name="PERF_LRZ_STALL_CYCLES_RB_BPLANE"/> - <value value="26" name="PERF_LRZ_STALL_CYCLES_VC"/> - <value value="27" name="PERF_LRZ_RAS_MASK_TRANS"/> -</enum> - -<enum name="a6xx_cmp_perfcounter_select"> - <value value="0" name="PERF_CMPDECMP_STALL_CYCLES_ARB"/> - <value value="1" name="PERF_CMPDECMP_VBIF_LATENCY_CYCLES"/> - <value value="2" name="PERF_CMPDECMP_VBIF_LATENCY_SAMPLES"/> - <value value="3" name="PERF_CMPDECMP_VBIF_READ_DATA_CCU"/> - <value value="4" name="PERF_CMPDECMP_VBIF_WRITE_DATA_CCU"/> - <value value="5" name="PERF_CMPDECMP_VBIF_READ_REQUEST"/> - <value value="6" name="PERF_CMPDECMP_VBIF_WRITE_REQUEST"/> - <value value="7" name="PERF_CMPDECMP_VBIF_READ_DATA"/> - <value value="8" name="PERF_CMPDECMP_VBIF_WRITE_DATA"/> - <value value="9" name="PERF_CMPDECMP_FLAG_FETCH_CYCLES"/> - <value value="10" name="PERF_CMPDECMP_FLAG_FETCH_SAMPLES"/> - <value value="11" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG1_COUNT"/> - <value value="12" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG2_COUNT"/> - <value value="13" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG3_COUNT"/> - <value value="14" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG4_COUNT"/> - <value value="15" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG5_COUNT"/> - <value value="16" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG6_COUNT"/> - <value value="17" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG8_COUNT"/> - <value value="18" name="PERF_CMPDECMP_COLOR_WRITE_FLAG1_COUNT"/> - <value value="19" name="PERF_CMPDECMP_COLOR_WRITE_FLAG2_COUNT"/> - <value value="20" name="PERF_CMPDECMP_COLOR_WRITE_FLAG3_COUNT"/> - <value value="21" name="PERF_CMPDECMP_COLOR_WRITE_FLAG4_COUNT"/> - <value value="22" name="PERF_CMPDECMP_COLOR_WRITE_FLAG5_COUNT"/> - <value value="23" name="PERF_CMPDECMP_COLOR_WRITE_FLAG6_COUNT"/> - <value value="24" name="PERF_CMPDECMP_COLOR_WRITE_FLAG8_COUNT"/> - <value value="25" name="PERF_CMPDECMP_2D_STALL_CYCLES_VBIF_REQ"/> - <value value="26" name="PERF_CMPDECMP_2D_STALL_CYCLES_VBIF_WR"/> - <value value="27" name="PERF_CMPDECMP_2D_STALL_CYCLES_VBIF_RETURN"/> - <value value="28" name="PERF_CMPDECMP_2D_RD_DATA"/> - <value value="29" name="PERF_CMPDECMP_2D_WR_DATA"/> - <value value="30" name="PERF_CMPDECMP_VBIF_READ_DATA_UCHE_CH0"/> - <value value="31" name="PERF_CMPDECMP_VBIF_READ_DATA_UCHE_CH1"/> - <value value="32" name="PERF_CMPDECMP_2D_OUTPUT_TRANS"/> - <value value="33" name="PERF_CMPDECMP_VBIF_WRITE_DATA_UCHE"/> - <value value="34" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG0_COUNT"/> - <value value="35" name="PERF_CMPDECMP_COLOR_WRITE_FLAG0_COUNT"/> - <value value="36" name="PERF_CMPDECMP_COLOR_WRITE_FLAGALPHA_COUNT"/> - <value value="37" name="PERF_CMPDECMP_2D_BUSY_CYCLES"/> - <value value="38" name="PERF_CMPDECMP_2D_REORDER_STARVE_CYCLES"/> - <value value="39" name="PERF_CMPDECMP_2D_PIXELS"/> -</enum> - -<!-- -Used in a6xx_2d_blit_cntl.. the value mostly seems to correlate to the -component type/size, so I think it relates to internal format used for -blending? The one exception is that 16b unorm and 32b float use the -same value... maybe 16b unorm is uncommon enough that it was just easier -to upconvert to 32b float internally? - - 8b unorm: 10 (sometimes 0, is the high bit part of something else?) -16b unorm: 4 - -32b int: 7 -16b int: 6 - 8b int: 5 - -32b float: 4 -16b float: 3 - --> -<enum name="a6xx_2d_ifmt"> - <value value="0x10" name="R2D_UNORM8"/> - <value value="0x7" name="R2D_INT32"/> - <value value="0x6" name="R2D_INT16"/> - <value value="0x5" name="R2D_INT8"/> - <value value="0x4" name="R2D_FLOAT32"/> - <value value="0x3" name="R2D_FLOAT16"/> - <value value="0x1" name="R2D_UNORM8_SRGB"/> - <value value="0x0" name="R2D_RAW"/> -</enum> - -<enum name="a6xx_ztest_mode"> - <doc>Allow early z-test and early-lrz (if applicable)</doc> - <value value="0x0" name="A6XX_EARLY_Z"/> - <doc>Disable early z-test and early-lrz test (if applicable)</doc> - <value value="0x1" name="A6XX_LATE_Z"/> - <doc> - A special mode that allows early-lrz test but disables - early-z test. Which might sound a bit funny, since - lrz-test happens before z-test. But as long as a couple - conditions are maintained this allows using lrz-test in - cases where fragment shader has kill/discard: - - 1) Disable lrz-write in cases where it is uncertain during - binning pass that a fragment will pass. Ie. if frag - shader has-kill, writes-z, or alpha/stencil test is - enabled. (For correctness, lrz-write must be disabled - when blend is enabled.) This is analogous to how a - z-prepass works. - - 2) Disable lrz-write and test if a depth-test direction - reversal is detected. Due to condition (1), the contents - of the lrz buffer are a conservative estimation of the - depth buffer during the draw pass. Meaning that geometry - that we know for certain will not be visible will not pass - lrz-test. But geometry which may be (or contributes to - blend) will pass the lrz-test. - - This allows us to keep early-lrz-test in cases where the frag - shader does not write-z (ie. we know the z-value before FS) - and does not have side-effects (image/ssbo writes, etc), but - does have kill/discard. Which turns out to be a common - enough case that it is useful to keep early-lrz test against - the conservative lrz buffer to discard fragments that we - know will definitely not be visible. - </doc> - <value value="0x2" name="A6XX_EARLY_LRZ_LATE_Z"/> - <doc>Not a real hw value, used internally by mesa</doc> - <value value="0x3" name="A6XX_INVALID_ZTEST"/> -</enum> - -<enum name="a6xx_tess_spacing"> - <value value="0x0" name="TESS_EQUAL"/> - <value value="0x2" name="TESS_FRACTIONAL_ODD"/> - <value value="0x3" name="TESS_FRACTIONAL_EVEN"/> -</enum> -<enum name="a6xx_tess_output"> - <value value="0x0" name="TESS_POINTS"/> - <value value="0x1" name="TESS_LINES"/> - <value value="0x2" name="TESS_CW_TRIS"/> - <value value="0x3" name="TESS_CCW_TRIS"/> -</enum> - -<enum name="a7xx_cp_perfcounter_select"> - <value value="0" name="A7XX_PERF_CP_ALWAYS_COUNT"/> - <value value="1" name="A7XX_PERF_CP_BUSY_GFX_CORE_IDLE"/> - <value value="2" name="A7XX_PERF_CP_BUSY_CYCLES"/> - <value value="3" name="A7XX_PERF_CP_NUM_PREEMPTIONS"/> - <value value="4" name="A7XX_PERF_CP_PREEMPTION_REACTION_DELAY"/> - <value value="5" name="A7XX_PERF_CP_PREEMPTION_SWITCH_OUT_TIME"/> - <value value="6" name="A7XX_PERF_CP_PREEMPTION_SWITCH_IN_TIME"/> - <value value="7" name="A7XX_PERF_CP_DEAD_DRAWS_IN_BIN_RENDER"/> - <value value="8" name="A7XX_PERF_CP_PREDICATED_DRAWS_KILLED"/> - <value value="9" name="A7XX_PERF_CP_MODE_SWITCH"/> - <value value="10" name="A7XX_PERF_CP_ZPASS_DONE"/> - <value value="11" name="A7XX_PERF_CP_CONTEXT_DONE"/> - <value value="12" name="A7XX_PERF_CP_CACHE_FLUSH"/> - <value value="13" name="A7XX_PERF_CP_LONG_PREEMPTIONS"/> - <value value="14" name="A7XX_PERF_CP_SQE_I_CACHE_STARVE"/> - <value value="15" name="A7XX_PERF_CP_SQE_IDLE"/> - <value value="16" name="A7XX_PERF_CP_SQE_PM4_STARVE_RB_IB"/> - <value value="17" name="A7XX_PERF_CP_SQE_PM4_STARVE_SDS"/> - <value value="18" name="A7XX_PERF_CP_SQE_MRB_STARVE"/> - <value value="19" name="A7XX_PERF_CP_SQE_RRB_STARVE"/> - <value value="20" name="A7XX_PERF_CP_SQE_VSD_STARVE"/> - <value value="21" name="A7XX_PERF_CP_VSD_DECODE_STARVE"/> - <value value="22" name="A7XX_PERF_CP_SQE_PIPE_OUT_STALL"/> - <value value="23" name="A7XX_PERF_CP_SQE_SYNC_STALL"/> - <value value="24" name="A7XX_PERF_CP_SQE_PM4_WFI_STALL"/> - <value value="25" name="A7XX_PERF_CP_SQE_SYS_WFI_STALL"/> - <value value="26" name="A7XX_PERF_CP_SQE_T4_EXEC"/> - <value value="27" name="A7XX_PERF_CP_SQE_LOAD_STATE_EXEC"/> - <value value="28" name="A7XX_PERF_CP_SQE_SAVE_SDS_STATE"/> - <value value="29" name="A7XX_PERF_CP_SQE_DRAW_EXEC"/> - <value value="30" name="A7XX_PERF_CP_SQE_CTXT_REG_BUNCH_EXEC"/> - <value value="31" name="A7XX_PERF_CP_SQE_EXEC_PROFILED"/> - <value value="32" name="A7XX_PERF_CP_MEMORY_POOL_EMPTY"/> - <value value="33" name="A7XX_PERF_CP_MEMORY_POOL_SYNC_STALL"/> - <value value="34" name="A7XX_PERF_CP_MEMORY_POOL_ABOVE_THRESH"/> - <value value="35" name="A7XX_PERF_CP_AHB_WR_STALL_PRE_DRAWS"/> - <value value="36" name="A7XX_PERF_CP_AHB_STALL_SQE_GMU"/> - <value value="37" name="A7XX_PERF_CP_AHB_STALL_SQE_WR_OTHER"/> - <value value="38" name="A7XX_PERF_CP_AHB_STALL_SQE_RD_OTHER"/> - <value value="39" name="A7XX_PERF_CP_CLUSTER0_EMPTY"/> - <value value="40" name="A7XX_PERF_CP_CLUSTER1_EMPTY"/> - <value value="41" name="A7XX_PERF_CP_CLUSTER2_EMPTY"/> - <value value="42" name="A7XX_PERF_CP_CLUSTER3_EMPTY"/> - <value value="43" name="A7XX_PERF_CP_CLUSTER4_EMPTY"/> - <value value="44" name="A7XX_PERF_CP_CLUSTER5_EMPTY"/> - <value value="45" name="A7XX_PERF_CP_PM4_DATA"/> - <value value="46" name="A7XX_PERF_CP_PM4_HEADERS"/> - <value value="47" name="A7XX_PERF_CP_VBIF_READ_BEATS"/> - <value value="48" name="A7XX_PERF_CP_VBIF_WRITE_BEATS"/> - <value value="49" name="A7XX_PERF_CP_SQE_INSTR_COUNTER"/> - <value value="50" name="A7XX_PERF_CP_RESERVED_50"/> - <value value="51" name="A7XX_PERF_CP_RESERVED_51"/> - <value value="52" name="A7XX_PERF_CP_RESERVED_52"/> - <value value="53" name="A7XX_PERF_CP_RESERVED_53"/> - <value value="54" name="A7XX_PERF_CP_RESERVED_54"/> - <value value="55" name="A7XX_PERF_CP_RESERVED_55"/> - <value value="56" name="A7XX_PERF_CP_RESERVED_56"/> - <value value="57" name="A7XX_PERF_CP_RESERVED_57"/> - <value value="58" name="A7XX_PERF_CP_RESERVED_58"/> - <value value="59" name="A7XX_PERF_CP_RESERVED_59"/> - <value value="60" name="A7XX_PERF_CP_CLUSTER0_FULL"/> - <value value="61" name="A7XX_PERF_CP_CLUSTER1_FULL"/> - <value value="62" name="A7XX_PERF_CP_CLUSTER2_FULL"/> - <value value="63" name="A7XX_PERF_CP_CLUSTER3_FULL"/> - <value value="64" name="A7XX_PERF_CP_CLUSTER4_FULL"/> - <value value="65" name="A7XX_PERF_CP_CLUSTER5_FULL"/> - <value value="66" name="A7XX_PERF_CP_CLUSTER6_FULL"/> - <value value="67" name="A7XX_PERF_CP_CLUSTER6_EMPTY"/> - <value value="68" name="A7XX_PERF_CP_ICACHE_MISSES"/> - <value value="69" name="A7XX_PERF_CP_ICACHE_HITS"/> - <value value="70" name="A7XX_PERF_CP_ICACHE_STALL"/> - <value value="71" name="A7XX_PERF_CP_DCACHE_MISSES"/> - <value value="72" name="A7XX_PERF_CP_DCACHE_HITS"/> - <value value="73" name="A7XX_PERF_CP_DCACHE_STALLS"/> - <value value="74" name="A7XX_PERF_CP_AQE_SQE_STALL"/> - <value value="75" name="A7XX_PERF_CP_SQE_AQE_STARVE"/> - <value value="76" name="A7XX_PERF_CP_PREEMPT_LATENCY"/> - <value value="77" name="A7XX_PERF_CP_SQE_MD8_STALL_CYCLES"/> - <value value="78" name="A7XX_PERF_CP_SQE_MESH_EXEC_CYCLES"/> - <value value="79" name="A7XX_PERF_CP_AQE_NUM_AS_CHUNKS"/> - <value value="80" name="A7XX_PERF_CP_AQE_NUM_MS_CHUNKS"/> -</enum> - -<enum name="a7xx_rbbm_perfcounter_select"> - <value value="0" name="A7XX_PERF_RBBM_ALWAYS_COUNT"/> - <value value="1" name="A7XX_PERF_RBBM_ALWAYS_ON"/> - <value value="2" name="A7XX_PERF_RBBM_TSE_BUSY"/> - <value value="3" name="A7XX_PERF_RBBM_RAS_BUSY"/> - <value value="4" name="A7XX_PERF_RBBM_PC_DCALL_BUSY"/> - <value value="5" name="A7XX_PERF_RBBM_PC_VSD_BUSY"/> - <value value="6" name="A7XX_PERF_RBBM_STATUS_MASKED"/> - <value value="7" name="A7XX_PERF_RBBM_COM_BUSY"/> - <value value="8" name="A7XX_PERF_RBBM_DCOM_BUSY"/> - <value value="9" name="A7XX_PERF_RBBM_VBIF_BUSY"/> - <value value="10" name="A7XX_PERF_RBBM_VSC_BUSY"/> - <value value="11" name="A7XX_PERF_RBBM_TESS_BUSY"/> - <value value="12" name="A7XX_PERF_RBBM_UCHE_BUSY"/> - <value value="13" name="A7XX_PERF_RBBM_HLSQ_BUSY"/> -</enum> - -<enum name="a7xx_pc_perfcounter_select"> - <value value="0" name="A7XX_PERF_PC_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_PC_WORKING_CYCLES"/> - <value value="2" name="A7XX_PERF_PC_STALL_CYCLES_VFD"/> - <value value="3" name="A7XX_PERF_PC_RESERVED"/> - <value value="4" name="A7XX_PERF_PC_STALL_CYCLES_VPC"/> - <value value="5" name="A7XX_PERF_PC_STALL_CYCLES_UCHE"/> - <value value="6" name="A7XX_PERF_PC_STALL_CYCLES_TESS"/> - <value value="7" name="A7XX_PERF_PC_STALL_CYCLES_VFD_ONLY"/> - <value value="8" name="A7XX_PERF_PC_STALL_CYCLES_VPC_ONLY"/> - <value value="9" name="A7XX_PERF_PC_PASS1_TF_STALL_CYCLES"/> - <value value="10" name="A7XX_PERF_PC_STARVE_CYCLES_FOR_INDEX"/> - <value value="11" name="A7XX_PERF_PC_STARVE_CYCLES_FOR_TESS_FACTOR"/> - <value value="12" name="A7XX_PERF_PC_STARVE_CYCLES_FOR_VIZ_STREAM"/> - <value value="13" name="A7XX_PERF_PC_STARVE_CYCLES_DI"/> - <value value="14" name="A7XX_PERF_PC_VIS_STREAMS_LOADED"/> - <value value="15" name="A7XX_PERF_PC_INSTANCES"/> - <value value="16" name="A7XX_PERF_PC_VPC_PRIMITIVES"/> - <value value="17" name="A7XX_PERF_PC_DEAD_PRIM"/> - <value value="18" name="A7XX_PERF_PC_LIVE_PRIM"/> - <value value="19" name="A7XX_PERF_PC_VERTEX_HITS"/> - <value value="20" name="A7XX_PERF_PC_IA_VERTICES"/> - <value value="21" name="A7XX_PERF_PC_IA_PRIMITIVES"/> - <value value="22" name="A7XX_PERF_PC_RESERVED_22"/> - <value value="23" name="A7XX_PERF_PC_HS_INVOCATIONS"/> - <value value="24" name="A7XX_PERF_PC_DS_INVOCATIONS"/> - <value value="25" name="A7XX_PERF_PC_VS_INVOCATIONS"/> - <value value="26" name="A7XX_PERF_PC_GS_INVOCATIONS"/> - <value value="27" name="A7XX_PERF_PC_DS_PRIMITIVES"/> - <value value="28" name="A7XX_PERF_PC_3D_DRAWCALLS"/> - <value value="29" name="A7XX_PERF_PC_2D_DRAWCALLS"/> - <value value="30" name="A7XX_PERF_PC_NON_DRAWCALL_GLOBAL_EVENTS"/> - <value value="31" name="A7XX_PERF_PC_TESS_BUSY_CYCLES"/> - <value value="32" name="A7XX_PERF_PC_TESS_WORKING_CYCLES"/> - <value value="33" name="A7XX_PERF_PC_TESS_STALL_CYCLES_PC"/> - <value value="34" name="A7XX_PERF_PC_TESS_STARVE_CYCLES_PC"/> - <value value="35" name="A7XX_PERF_PC_TESS_SINGLE_PRIM_CYCLES"/> - <value value="36" name="A7XX_PERF_PC_TESS_PC_UV_TRANS"/> - <value value="37" name="A7XX_PERF_PC_TESS_PC_UV_PATCHES"/> - <value value="38" name="A7XX_PERF_PC_TESS_FACTOR_TRANS"/> - <value value="39" name="A7XX_PERF_PC_TAG_CHECKED_VERTICES"/> - <value value="40" name="A7XX_PERF_PC_MESH_VS_WAVES"/> - <value value="41" name="A7XX_PERF_PC_MESH_DRAWS"/> - <value value="42" name="A7XX_PERF_PC_MESH_DEAD_DRAWS"/> - <value value="43" name="A7XX_PERF_PC_MESH_MVIS_EN_DRAWS"/> - <value value="44" name="A7XX_PERF_PC_MESH_DEAD_PRIM"/> - <value value="45" name="A7XX_PERF_PC_MESH_LIVE_PRIM"/> - <value value="46" name="A7XX_PERF_PC_MESH_PA_EN_PRIM"/> - <value value="47" name="A7XX_PERF_PC_STARVE_CYCLES_FOR_MVIS_STREAM"/> - <value value="48" name="A7XX_PERF_PC_STARVE_CYCLES_PREDRAW"/> - <value value="49" name="A7XX_PERF_PC_STALL_CYCLES_COMPUTE_GFX"/> - <value value="50" name="A7XX_PERF_PC_STALL_CYCLES_GFX_COMPUTE"/> - <value value="51" name="A7XX_PERF_PC_TESS_PC_MULTI_PATCH_TRANS"/> -</enum> - -<enum name="a7xx_vfd_perfcounter_select"> - <value value="0" name="A7XX_PERF_VFD_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_VFD_STALL_CYCLES_UCHE"/> - <value value="2" name="A7XX_PERF_VFD_STALL_CYCLES_VPC_ALLOC"/> - <value value="3" name="A7XX_PERF_VFD_STALL_CYCLES_SP_INFO"/> - <value value="4" name="A7XX_PERF_VFD_STALL_CYCLES_SP_ATTR"/> - <value value="5" name="A7XX_PERF_VFD_STARVE_CYCLES_UCHE"/> - <value value="6" name="A7XX_PERF_VFD_RBUFFER_FULL"/> - <value value="7" name="A7XX_PERF_VFD_ATTR_INFO_FIFO_FULL"/> - <value value="8" name="A7XX_PERF_VFD_DECODED_ATTRIBUTE_BYTES"/> - <value value="9" name="A7XX_PERF_VFD_NUM_ATTRIBUTES"/> - <value value="10" name="A7XX_PERF_VFD_UPPER_SHADER_FIBERS"/> - <value value="11" name="A7XX_PERF_VFD_LOWER_SHADER_FIBERS"/> - <value value="12" name="A7XX_PERF_VFD_MODE_0_FIBERS"/> - <value value="13" name="A7XX_PERF_VFD_MODE_1_FIBERS"/> - <value value="14" name="A7XX_PERF_VFD_MODE_2_FIBERS"/> - <value value="15" name="A7XX_PERF_VFD_MODE_3_FIBERS"/> - <value value="16" name="A7XX_PERF_VFD_MODE_4_FIBERS"/> - <value value="17" name="A7XX_PERF_VFD_TOTAL_VERTICES"/> - <value value="18" name="A7XX_PERF_VFDP_STALL_CYCLES_VFD"/> - <value value="19" name="A7XX_PERF_VFDP_STALL_CYCLES_VFD_INDEX"/> - <value value="20" name="A7XX_PERF_VFDP_STALL_CYCLES_VFD_PROG"/> - <value value="21" name="A7XX_PERF_VFDP_STARVE_CYCLES_PC"/> - <value value="22" name="A7XX_PERF_VFDP_VS_STAGE_WAVES"/> - <value value="23" name="A7XX_PERF_VFD_STALL_CYCLES_PRG_END_FE"/> - <value value="24" name="A7XX_PERF_VFD_STALL_CYCLES_CBSYNC"/> -</enum> - -<enum name="a7xx_hlsq_perfcounter_select"> - <value value="0" name="A7XX_PERF_HLSQ_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_HLSQ_STALL_CYCLES_UCHE"/> - <value value="2" name="A7XX_PERF_HLSQ_STALL_CYCLES_SP_STATE"/> - <value value="3" name="A7XX_PERF_HLSQ_STALL_CYCLES_SP_FS_STAGE"/> - <value value="4" name="A7XX_PERF_HLSQ_UCHE_LATENCY_CYCLES"/> - <value value="5" name="A7XX_PERF_HLSQ_UCHE_LATENCY_COUNT"/> - <value value="6" name="A7XX_PERF_HLSQ_RESERVED_6"/> - <value value="7" name="A7XX_PERF_HLSQ_RESERVED_7"/> - <value value="8" name="A7XX_PERF_HLSQ_RESERVED_8"/> - <value value="9" name="A7XX_PERF_HLSQ_RESERVED_9"/> - <value value="10" name="A7XX_PERF_HLSQ_COMPUTE_DRAWCALLS"/> - <value value="11" name="A7XX_PERF_HLSQ_FS_DATA_WAIT_PROGRAMMING"/> - <value value="12" name="A7XX_PERF_HLSQ_DUAL_FS_PROG_ACTIVE"/> - <value value="13" name="A7XX_PERF_HLSQ_DUAL_VS_PROG_ACTIVE"/> - <value value="14" name="A7XX_PERF_HLSQ_FS_BATCH_COUNT_ZERO"/> - <value value="15" name="A7XX_PERF_HLSQ_VS_BATCH_COUNT_ZERO"/> - <value value="16" name="A7XX_PERF_HLSQ_WAVE_PENDING_NO_QUAD"/> - <value value="17" name="A7XX_PERF_HLSQ_WAVE_PENDING_NO_PRIM_BASE"/> - <value value="18" name="A7XX_PERF_HLSQ_STALL_CYCLES_VPC"/> - <value value="19" name="A7XX_PERF_HLSQ_RESERVED_19"/> - <value value="20" name="A7XX_PERF_HLSQ_DRAW_MODE_SWITCH_VSFS_SYNC"/> - <value value="21" name="A7XX_PERF_HLSQ_VSBR_STALL_CYCLES"/> - <value value="22" name="A7XX_PERF_HLSQ_FS_STALL_CYCLES"/> - <value value="23" name="A7XX_PERF_HLSQ_LPAC_STALL_CYCLES"/> - <value value="24" name="A7XX_PERF_HLSQ_BV_STALL_CYCLES"/> - <value value="25" name="A7XX_PERF_HLSQ_VSBR_DEREF_CYCLES"/> - <value value="26" name="A7XX_PERF_HLSQ_FS_DEREF_CYCLES"/> - <value value="27" name="A7XX_PERF_HLSQ_LPAC_DEREF_CYCLES"/> - <value value="28" name="A7XX_PERF_HLSQ_BV_DEREF_CYCLES"/> - <value value="29" name="A7XX_PERF_HLSQ_VSBR_S2W_CYCLES"/> - <value value="30" name="A7XX_PERF_HLSQ_FS_S2W_CYCLES"/> - <value value="31" name="A7XX_PERF_HLSQ_LPAC_S2W_CYCLES"/> - <value value="32" name="A7XX_PERF_HLSQ_BV_S2W_CYCLES"/> - <value value="33" name="A7XX_PERF_HLSQ_VSBR_WAIT_FS_S2W"/> - <value value="34" name="A7XX_PERF_HLSQ_FS_WAIT_VS_S2W"/> - <value value="35" name="A7XX_PERF_HLSQ_LPAC_WAIT_VS_S2W"/> - <value value="36" name="A7XX_PERF_HLSQ_BV_WAIT_FS_S2W"/> - <value value="37" name="A7XX_PERF_HLSQ_VS_WAIT_CONST_RESOURCE"/> - <value value="38" name="A7XX_PERF_HLSQ_FS_WAIT_SAME_VS_S2W"/> - <value value="39" name="A7XX_PERF_HLSQ_FS_STARVING_SP"/> - <value value="40" name="A7XX_PERF_HLSQ_VS_DATA_WAIT_PROGRAMMING"/> - <value value="41" name="A7XX_PERF_HLSQ_BV_DATA_WAIT_PROGRAMMING"/> - <value value="42" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXTS_VS"/> - <value value="43" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXT_CYCLES_VS"/> - <value value="44" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXTS_FS"/> - <value value="45" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXT_CYCLES_FS"/> - <value value="46" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXTS_BV"/> - <value value="47" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXT_CYCLES_BV"/> - <value value="48" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXTS_LPAC"/> - <value value="49" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXT_CYCLES_LPAC"/> - <value value="50" name="A7XX_PERF_HLSQ_SPTROC_STCHE_WARMUP_INC_VS"/> - <value value="51" name="A7XX_PERF_HLSQ_SPTROC_STCHE_WARMUP_INC_FS"/> - <value value="52" name="A7XX_PERF_HLSQ_SPTROC_STCHE_WARMUP_INC_BV"/> - <value value="53" name="A7XX_PERF_HLSQ_SPTROC_STCHE_WARMUP_INC_LPAC"/> - <value value="54" name="A7XX_PERF_HLSQ_SPTROC_STCHE_MISS_INC_VS"/> - <value value="55" name="A7XX_PERF_HLSQ_SPTROC_STCHE_MISS_INC_FS"/> - <value value="56" name="A7XX_PERF_HLSQ_SPTROC_STCHE_MISS_INC_BV"/> - <value value="57" name="A7XX_PERF_HLSQ_SPTROC_STCHE_MISS_INC_LPAC"/> -</enum> - -<enum name="a7xx_vpc_perfcounter_select"> - <value value="0" name="A7XX_PERF_VPC_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_VPC_WORKING_CYCLES"/> - <value value="2" name="A7XX_PERF_VPC_STALL_CYCLES_UCHE"/> - <value value="3" name="A7XX_PERF_VPC_STALL_CYCLES_VFD_WACK"/> - <value value="4" name="A7XX_PERF_VPC_STALL_CYCLES_HLSQ_PRIM_ALLOC"/> - <value value="5" name="A7XX_PERF_VPC_RESERVED_5"/> - <value value="6" name="A7XX_PERF_VPC_STALL_CYCLES_SP_LM"/> - <value value="7" name="A7XX_PERF_VPC_STARVE_CYCLES_SP"/> - <value value="8" name="A7XX_PERF_VPC_STARVE_CYCLES_LRZ"/> - <value value="9" name="A7XX_PERF_VPC_PC_PRIMITIVES"/> - <value value="10" name="A7XX_PERF_VPC_SP_COMPONENTS"/> - <value value="11" name="A7XX_PERF_VPC_STALL_CYCLES_VPCRAM_POS"/> - <value value="12" name="A7XX_PERF_VPC_LRZ_ASSIGN_PRIMITIVES"/> - <value value="13" name="A7XX_PERF_VPC_RB_VISIBLE_PRIMITIVES"/> - <value value="14" name="A7XX_PERF_VPC_LM_TRANSACTION"/> - <value value="15" name="A7XX_PERF_VPC_STREAMOUT_TRANSACTION"/> - <value value="16" name="A7XX_PERF_VPC_VS_BUSY_CYCLES"/> - <value value="17" name="A7XX_PERF_VPC_PS_BUSY_CYCLES"/> - <value value="18" name="A7XX_PERF_VPC_VS_WORKING_CYCLES"/> - <value value="19" name="A7XX_PERF_VPC_PS_WORKING_CYCLES"/> - <value value="20" name="A7XX_PERF_VPC_STARVE_CYCLES_RB"/> - <value value="21" name="A7XX_PERF_VPC_NUM_VPCRAM_READ_POS"/> - <value value="22" name="A7XX_PERF_VPC_WIT_FULL_CYCLES"/> - <value value="23" name="A7XX_PERF_VPC_VPCRAM_FULL_CYCLES"/> - <value value="24" name="A7XX_PERF_VPC_LM_FULL_WAIT_FOR_INTP_END"/> - <value value="25" name="A7XX_PERF_VPC_NUM_VPCRAM_WRITE"/> - <value value="26" name="A7XX_PERF_VPC_NUM_VPCRAM_READ_SO"/> - <value value="27" name="A7XX_PERF_VPC_NUM_ATTR_REQ_LM"/> - <value value="28" name="A7XX_PERF_VPC_STALL_CYCLE_TSE"/> - <value value="29" name="A7XX_PERF_VPC_TSE_PRIMITIVES"/> - <value value="30" name="A7XX_PERF_VPC_GS_PRIMITIVES"/> - <value value="31" name="A7XX_PERF_VPC_TSE_TRANSACTIONS"/> - <value value="32" name="A7XX_PERF_VPC_STALL_CYCLES_CCU"/> - <value value="33" name="A7XX_PERF_VPC_NUM_WM_HIT"/> - <value value="34" name="A7XX_PERF_VPC_STALL_DQ_WACK"/> - <value value="35" name="A7XX_PERF_VPC_STALL_CYCLES_CCHE"/> - <value value="36" name="A7XX_PERF_VPC_STARVE_CYCLES_CCHE"/> - <value value="37" name="A7XX_PERF_VPC_NUM_PA_REQ"/> - <value value="38" name="A7XX_PERF_VPC_NUM_LM_REQ_HIT"/> - <value value="39" name="A7XX_PERF_VPC_CCHE_REQBUF_FULL"/> - <value value="40" name="A7XX_PERF_VPC_STALL_CYCLES_LM_ACK"/> - <value value="41" name="A7XX_PERF_VPC_STALL_CYCLES_PRG_END_FE"/> - <value value="42" name="A7XX_PERF_VPC_STALL_CYCLES_PRG_END_PCVS"/> - <value value="43" name="A7XX_PERF_VPC_STALL_CYCLES_PRG_END_VPCPS"/> -</enum> - -<enum name="a7xx_tse_perfcounter_select"> - <value value="0" name="A7XX_PERF_TSE_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_TSE_CLIPPING_CYCLES"/> - <value value="2" name="A7XX_PERF_TSE_STALL_CYCLES_RAS"/> - <value value="3" name="A7XX_PERF_TSE_STALL_CYCLES_LRZ_BARYPLANE"/> - <value value="4" name="A7XX_PERF_TSE_STALL_CYCLES_LRZ_ZPLANE"/> - <value value="5" name="A7XX_PERF_TSE_STARVE_CYCLES_PC"/> - <value value="6" name="A7XX_PERF_TSE_INPUT_PRIM"/> - <value value="7" name="A7XX_PERF_TSE_INPUT_NULL_PRIM"/> - <value value="8" name="A7XX_PERF_TSE_TRIVAL_REJ_PRIM"/> - <value value="9" name="A7XX_PERF_TSE_CLIPPED_PRIM"/> - <value value="10" name="A7XX_PERF_TSE_ZERO_AREA_PRIM"/> - <value value="11" name="A7XX_PERF_TSE_FACENESS_CULLED_PRIM"/> - <value value="12" name="A7XX_PERF_TSE_ZERO_PIXEL_PRIM"/> - <value value="13" name="A7XX_PERF_TSE_OUTPUT_NULL_PRIM"/> - <value value="14" name="A7XX_PERF_TSE_OUTPUT_VISIBLE_PRIM"/> - <value value="15" name="A7XX_PERF_TSE_CINVOCATION"/> - <value value="16" name="A7XX_PERF_TSE_CPRIMITIVES"/> - <value value="17" name="A7XX_PERF_TSE_2D_INPUT_PRIM"/> - <value value="18" name="A7XX_PERF_TSE_2D_ALIVE_CYCLES"/> - <value value="19" name="A7XX_PERF_TSE_CLIP_PLANES"/> -</enum> - -<enum name="a7xx_ras_perfcounter_select"> - <value value="0" name="A7XX_PERF_RAS_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_RAS_SUPERTILE_ACTIVE_CYCLES"/> - <value value="2" name="A7XX_PERF_RAS_STALL_CYCLES_LRZ"/> - <value value="3" name="A7XX_PERF_RAS_STARVE_CYCLES_TSE"/> - <value value="4" name="A7XX_PERF_RAS_SUPER_TILES"/> - <value value="5" name="A7XX_PERF_RAS_8X4_TILES"/> - <value value="6" name="A7XX_PERF_RAS_MASKGEN_ACTIVE"/> - <value value="7" name="A7XX_PERF_RAS_FULLY_COVERED_SUPER_TILES"/> - <value value="8" name="A7XX_PERF_RAS_FULLY_COVERED_8X4_TILES"/> - <value value="9" name="A7XX_PERF_RAS_PRIM_KILLED_INVISILBE"/> - <value value="10" name="A7XX_PERF_RAS_SUPERTILE_GEN_ACTIVE_CYCLES"/> - <value value="11" name="A7XX_PERF_RAS_LRZ_INTF_WORKING_CYCLES"/> - <value value="12" name="A7XX_PERF_RAS_BLOCKS"/> - <value value="13" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_0_WORKING_CC_l2"/> - <value value="14" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_1_WORKING_CC_l2"/> - <value value="15" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_2_WORKING_CC_l2"/> - <value value="16" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_3_WORKING_CC_l2"/> - <value value="17" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_4_WORKING_CC_l2"/> - <value value="18" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_5_WORKING_CC_l2"/> - <value value="19" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_6_WORKING_CC_l2"/> - <value value="20" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_7_WORKING_CC_l2"/> - <value value="21" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_8_WORKING_CC_l2"/> - <value value="22" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_9_WORKING_CC_l2"/> - <value value="23" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_10_WORKING_CC_l2"/> - <value value="24" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_11_WORKING_CC_l2"/> - <value value="25" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_12_WORKING_CC_l2"/> - <value value="26" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_13_WORKING_CC_l2"/> - <value value="27" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_14_WORKING_CC_l2"/> - <value value="28" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_15_WORKING_CC_l2"/> - <value value="29" name="A7XX_PERF_RAS_FALSE_PARTIAL_STILE"/> - -</enum> - -<enum name="a7xx_uche_perfcounter_select"> - <value value="0" name="A7XX_PERF_UCHE_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_UCHE_STALL_CYCLES_ARBITER"/> - <value value="2" name="A7XX_PERF_UCHE_VBIF_LATENCY_CYCLES"/> - <value value="3" name="A7XX_PERF_UCHE_VBIF_LATENCY_SAMPLES"/> - <value value="4" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_TP"/> - <value value="5" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_VFD"/> - <value value="6" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_HLSQ"/> - <value value="7" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_LRZ"/> - <value value="8" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_SP"/> - <value value="9" name="A7XX_PERF_UCHE_READ_REQUESTS_TP"/> - <value value="10" name="A7XX_PERF_UCHE_READ_REQUESTS_VFD"/> - <value value="11" name="A7XX_PERF_UCHE_READ_REQUESTS_HLSQ"/> - <value value="12" name="A7XX_PERF_UCHE_READ_REQUESTS_LRZ"/> - <value value="13" name="A7XX_PERF_UCHE_READ_REQUESTS_SP"/> - <value value="14" name="A7XX_PERF_UCHE_WRITE_REQUESTS_LRZ"/> - <value value="15" name="A7XX_PERF_UCHE_WRITE_REQUESTS_SP"/> - <value value="16" name="A7XX_PERF_UCHE_WRITE_REQUESTS_VPC"/> - <value value="17" name="A7XX_PERF_UCHE_WRITE_REQUESTS_VSC"/> - <value value="18" name="A7XX_PERF_UCHE_EVICTS"/> - <value value="19" name="A7XX_PERF_UCHE_BANK_REQ0"/> - <value value="20" name="A7XX_PERF_UCHE_BANK_REQ1"/> - <value value="21" name="A7XX_PERF_UCHE_BANK_REQ2"/> - <value value="22" name="A7XX_PERF_UCHE_BANK_REQ3"/> - <value value="23" name="A7XX_PERF_UCHE_BANK_REQ4"/> - <value value="24" name="A7XX_PERF_UCHE_BANK_REQ5"/> - <value value="25" name="A7XX_PERF_UCHE_BANK_REQ6"/> - <value value="26" name="A7XX_PERF_UCHE_BANK_REQ7"/> - <value value="27" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_CH0"/> - <value value="28" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_CH1"/> - <value value="29" name="A7XX_PERF_UCHE_GMEM_READ_BEATS"/> - <value value="30" name="A7XX_PERF_UCHE_TPH_REF_FULL"/> - <value value="31" name="A7XX_PERF_UCHE_TPH_VICTIM_FULL"/> - <value value="32" name="A7XX_PERF_UCHE_TPH_EXT_FULL"/> - <value value="33" name="A7XX_PERF_UCHE_VBIF_STALL_WRITE_DATA"/> - <value value="34" name="A7XX_PERF_UCHE_DCMP_LATENCY_SAMPLES"/> - <value value="35" name="A7XX_PERF_UCHE_DCMP_LATENCY_CYCLES"/> - <value value="36" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_PC"/> - <value value="37" name="A7XX_PERF_UCHE_READ_REQUESTS_PC"/> - <value value="38" name="A7XX_PERF_UCHE_RAM_READ_REQ"/> - <value value="39" name="A7XX_PERF_UCHE_RAM_WRITE_REQ"/> - <value value="40" name="A7XX_PERF_UCHE_STARVED_CYCLES_VBIF_DECMP"/> - <value value="41" name="A7XX_PERF_UCHE_STALL_CYCLES_DECMP"/> - <value value="42" name="A7XX_PERF_UCHE_ARBITER_STALL_CYCLES_VBIF"/> - <value value="43" name="A7XX_PERF_UCHE_READ_REQUESTS_TP_UBWC"/> - <value value="44" name="A7XX_PERF_UCHE_READ_REQUESTS_TP_NONUBWC"/> - <value value="45" name="A7XX_PERF_UCHE_READ_REQUESTS_TP_GMEM"/> - <value value="46" name="A7XX_PERF_UCHE_LONG_LINE_ALL_EVICTS_KAILUA"/> - <value value="47" name="A7XX_PERF_UCHE_LONG_LINE_PARTIAL_EVICTS_KAILUA"/> - <value value="48" name="A7XX_PERF_UCHE_TPH_CONFLICT_CL_CCHE"/> - <value value="49" name="A7XX_PERF_UCHE_TPH_CONFLICT_CL_OTHER_KAILUA"/> - <value value="50" name="A7XX_PERF_UCHE_DBANK_CONFLICT_CL_CCHE"/> - <value value="51" name="A7XX_PERF_UCHE_DBANK_CONFLICT_CL_OTHER_CLIENTS"/> - <value value="52" name="A7XX_PERF_UCHE_VBIF_WRITE_BEATS_CH0"/> - <value value="53" name="A7XX_PERF_UCHE_VBIF_WRITE_BEATS_CH1"/> - <value value="54" name="A7XX_PERF_UCHE_CCHE_TPH_QUEUE_FULL"/> - <value value="55" name="A7XX_PERF_UCHE_CCHE_DPH_QUEUE_FULL"/> - <value value="56" name="A7XX_PERF_UCHE_GMEM_WRITE_BEATS"/> - <value value="57" name="A7XX_PERF_UCHE_UBWC_READ_BEATS"/> - <value value="58" name="A7XX_PERF_UCHE_UBWC_WRITE_BEATS"/> -</enum> - -<enum name="a7xx_tp_perfcounter_select"> - <value value="0" name="A7XX_PERF_TP_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_TP_STALL_CYCLES_UCHE"/> - <value value="2" name="A7XX_PERF_TP_LATENCY_CYCLES"/> - <value value="3" name="A7XX_PERF_TP_LATENCY_TRANS"/> - <value value="4" name="A7XX_PERF_TP_FLAG_FIFO_DELAY_SAMPLES"/> - <value value="5" name="A7XX_PERF_TP_FLAG_FIFO_DELAY_CYCLES"/> - <value value="6" name="A7XX_PERF_TP_L1_CACHELINE_REQUESTS"/> - <value value="7" name="A7XX_PERF_TP_L1_CACHELINE_MISSES"/> - <value value="8" name="A7XX_PERF_TP_SP_TP_TRANS"/> - <value value="9" name="A7XX_PERF_TP_TP_SP_TRANS"/> - <value value="10" name="A7XX_PERF_TP_OUTPUT_PIXELS"/> - <value value="11" name="A7XX_PERF_TP_FILTER_WORKLOAD_16BIT"/> - <value value="12" name="A7XX_PERF_TP_FILTER_WORKLOAD_32BIT"/> - <value value="13" name="A7XX_PERF_TP_QUADS_RECEIVED"/> - <value value="14" name="A7XX_PERF_TP_QUADS_OFFSET"/> - <value value="15" name="A7XX_PERF_TP_QUADS_SHADOW"/> - <value value="16" name="A7XX_PERF_TP_QUADS_ARRAY"/> - <value value="17" name="A7XX_PERF_TP_QUADS_GRADIENT"/> - <value value="18" name="A7XX_PERF_TP_QUADS_1D"/> - <value value="19" name="A7XX_PERF_TP_QUADS_2D"/> - <value value="20" name="A7XX_PERF_TP_QUADS_BUFFER"/> - <value value="21" name="A7XX_PERF_TP_QUADS_3D"/> - <value value="22" name="A7XX_PERF_TP_QUADS_CUBE"/> - <value value="23" name="A7XX_PERF_TP_DIVERGENT_QUADS_RECEIVED"/> - <value value="24" name="A7XX_PERF_TP_PRT_NON_RESIDENT_EVENTS"/> - <value value="25" name="A7XX_PERF_TP_OUTPUT_PIXELS_POINT"/> - <value value="26" name="A7XX_PERF_TP_OUTPUT_PIXELS_BILINEAR"/> - <value value="27" name="A7XX_PERF_TP_OUTPUT_PIXELS_MIP"/> - <value value="28" name="A7XX_PERF_TP_OUTPUT_PIXELS_ANISO"/> - <value value="29" name="A7XX_PERF_TP_OUTPUT_PIXELS_ZERO_LOD"/> - <value value="30" name="A7XX_PERF_TP_FLAG_CACHE_REQUESTS"/> - <value value="31" name="A7XX_PERF_TP_FLAG_CACHE_MISSES"/> - <value value="32" name="A7XX_PERF_TP_L1_5_L2_REQUESTS"/> - <value value="33" name="A7XX_PERF_TP_2D_OUTPUT_PIXELS"/> - <value value="34" name="A7XX_PERF_TP_2D_OUTPUT_PIXELS_POINT"/> - <value value="35" name="A7XX_PERF_TP_2D_OUTPUT_PIXELS_BILINEAR"/> - <value value="36" name="A7XX_PERF_TP_2D_FILTER_WORKLOAD_16BIT"/> - <value value="37" name="A7XX_PERF_TP_2D_FILTER_WORKLOAD_32BIT"/> - <value value="38" name="A7XX_PERF_TP_TPA2TPC_TRANS"/> - <value value="39" name="A7XX_PERF_TP_L1_MISSES_ASTC_1TILE"/> - <value value="40" name="A7XX_PERF_TP_L1_MISSES_ASTC_2TILE"/> - <value value="41" name="A7XX_PERF_TP_L1_MISSES_ASTC_4TILE"/> - <value value="42" name="A7XX_PERF_TP_L1_5_COMPRESS_REQS"/> - <value value="43" name="A7XX_PERF_TP_L1_5_L2_COMPRESS_MISS"/> - <value value="44" name="A7XX_PERF_TP_L1_BANK_CONFLICT"/> - <value value="45" name="A7XX_PERF_TP_L1_5_MISS_LATENCY_CYCLES"/> - <value value="46" name="A7XX_PERF_TP_L1_5_MISS_LATENCY_TRANS"/> - <value value="47" name="A7XX_PERF_TP_QUADS_CONSTANT_MULTIPLIED"/> - <value value="48" name="A7XX_PERF_TP_FRONTEND_WORKING_CYCLES"/> - <value value="49" name="A7XX_PERF_TP_L1_TAG_WORKING_CYCLES"/> - <value value="50" name="A7XX_PERF_TP_L1_DATA_WRITE_WORKING_CYCLES"/> - <value value="51" name="A7XX_PERF_TP_PRE_L1_DECOM_WORKING_CYCLES"/> - <value value="52" name="A7XX_PERF_TP_BACKEND_WORKING_CYCLES"/> - <value value="53" name="A7XX_PERF_TP_L1_5_CACHE_WORKING_CYCLES"/> - <value value="54" name="A7XX_PERF_TP_STARVE_CYCLES_SP"/> - <value value="55" name="A7XX_PERF_TP_STARVE_CYCLES_UCHE"/> - <value value="56" name="A7XX_PERF_TP_STALL_CYCLES_UFC"/> - <value value="57" name="A7XX_PERF_TP_FORMAT_DECOMP"/> - <value value="58" name="A7XX_PERF_TP_FILTER_POINT_FP16"/> - <value value="59" name="A7XX_PERF_TP_FILTER_POINT_FP32"/> - <value value="60" name="A7XX_PERF_TP_LATENCY_FIFO_FULL"/> - <value value="61" name="A7XX_PERF_TP_RESERVED_61"/> - <value value="62" name="A7XX_PERF_TP_RESERVED_62"/> - <value value="63" name="A7XX_PERF_TP_RESERVED_63"/> - <value value="64" name="A7XX_PERF_TP_RESERVED_64"/> - <value value="65" name="A7XX_PERF_TP_RESERVED_65"/> - <value value="66" name="A7XX_PERF_TP_RESERVED_66"/> - <value value="67" name="A7XX_PERF_TP_RESERVED_67"/> - <value value="68" name="A7XX_PERF_TP_RESERVED_68"/> - <value value="69" name="A7XX_PERF_TP_RESERVED_69"/> - <value value="70" name="A7XX_PERF_TP_RESERVED_70"/> - <value value="71" name="A7XX_PERF_TP_RESERVED_71"/> - <value value="72" name="A7XX_PERF_TP_RESERVED_72"/> - <value value="73" name="A7XX_PERF_TP_RESERVED_73"/> - <value value="74" name="A7XX_PERF_TP_RESERVED_74"/> - <value value="75" name="A7XX_PERF_TP_RESERVED_75"/> - <value value="76" name="A7XX_PERF_TP_RESERVED_76"/> - <value value="77" name="A7XX_PERF_TP_RESERVED_77"/> - <value value="78" name="A7XX_PERF_TP_RESERVED_78"/> - <value value="79" name="A7XX_PERF_TP_RESERVED_79"/> - <value value="80" name="A7XX_PERF_TP_RESERVED_80"/> - <value value="81" name="A7XX_PERF_TP_RESERVED_81"/> - <value value="82" name="A7XX_PERF_TP_RESERVED_82"/> - <value value="83" name="A7XX_PERF_TP_RESERVED_83"/> - <value value="84" name="A7XX_PERF_TP_RESERVED_84"/> - <value value="85" name="A7XX_PERF_TP_RESERVED_85"/> - <value value="86" name="A7XX_PERF_TP_RESERVED_86"/> - <value value="87" name="A7XX_PERF_TP_RESERVED_87"/> - <value value="88" name="A7XX_PERF_TP_RESERVED_88"/> - <value value="89" name="A7XX_PERF_TP_RESERVED_89"/> - <value value="90" name="A7XX_PERF_TP_RESERVED_90"/> - <value value="91" name="A7XX_PERF_TP_RESERVED_91"/> - <value value="92" name="A7XX_PERF_TP_RESERVED_92"/> - <value value="93" name="A7XX_PERF_TP_RESERVED_93"/> - <value value="94" name="A7XX_PERF_TP_RESERVED_94"/> - <value value="95" name="A7XX_PERF_TP_RESERVED_95"/> - <value value="96" name="A7XX_PERF_TP_RESERVED_96"/> - <value value="97" name="A7XX_PERF_TP_RESERVED_97"/> - <value value="98" name="A7XX_PERF_TP_RESERVED_98"/> - <value value="99" name="A7XX_PERF_TP_RESERVED_99"/> - <value value="100" name="A7XX_PERF_TP_RESERVED_100"/> - <value value="101" name="A7XX_PERF_TP_RESERVED_101"/> - <value value="102" name="A7XX_PERF_TP_RESERVED_102"/> - <value value="103" name="A7XX_PERF_TP_RESERVED_103"/> - <value value="104" name="A7XX_PERF_TP_RESERVED_104"/> - <value value="105" name="A7XX_PERF_TP_RESERVED_105"/> - <value value="106" name="A7XX_PERF_TP_RESERVED_106"/> - <value value="107" name="A7XX_PERF_TP_RESERVED_107"/> - <value value="108" name="A7XX_PERF_TP_RESERVED_108"/> - <value value="109" name="A7XX_PERF_TP_RESERVED_109"/> - <value value="110" name="A7XX_PERF_TP_RESERVED_110"/> - <value value="111" name="A7XX_PERF_TP_RESERVED_111"/> - <value value="112" name="A7XX_PERF_TP_RESERVED_112"/> - <value value="113" name="A7XX_PERF_TP_RESERVED_113"/> - <value value="114" name="A7XX_PERF_TP_RESERVED_114"/> - <value value="115" name="A7XX_PERF_TP_RESERVED_115"/> - <value value="116" name="A7XX_PERF_TP_RESERVED_116"/> - <value value="117" name="A7XX_PERF_TP_RESERVED_117"/> - <value value="118" name="A7XX_PERF_TP_RESERVED_118"/> - <value value="119" name="A7XX_PERF_TP_RESERVED_119"/> - <value value="120" name="A7XX_PERF_TP_RESERVED_120"/> - <value value="121" name="A7XX_PERF_TP_RESERVED_121"/> - <value value="122" name="A7XX_PERF_TP_RESERVED_122"/> - <value value="123" name="A7XX_PERF_TP_RESERVED_123"/> - <value value="124" name="A7XX_PERF_TP_RESERVED_124"/> - <value value="125" name="A7XX_PERF_TP_RESERVED_125"/> - <value value="126" name="A7XX_PERF_TP_RESERVED_126"/> - <value value="127" name="A7XX_PERF_TP_RESERVED_127"/> - <value value="128" name="A7XX_PERF_TP_FORMAT_DECOMP_BILINEAR"/> - <value value="129" name="A7XX_PERF_TP_PACKED_POINT_BOTH_VALID_FP16"/> - <value value="130" name="A7XX_PERF_TP_PACKED_POINT_SINGLE_VALID_FP16"/> - <value value="131" name="A7XX_PERF_TP_PACKED_POINT_BOTH_VALID_FP32"/> - <value value="132" name="A7XX_PERF_TP_PACKED_POINT_SINGLE_VALID_FP32"/> -</enum> - -<enum name="a7xx_sp_perfcounter_select"> - <value value="0" name="A7XX_PERF_SP_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_SP_ALU_WORKING_CYCLES"/> - <value value="2" name="A7XX_PERF_SP_EFU_WORKING_CYCLES"/> - <value value="3" name="A7XX_PERF_SP_STALL_CYCLES_VPC"/> - <value value="4" name="A7XX_PERF_SP_STALL_CYCLES_TP"/> - <value value="5" name="A7XX_PERF_SP_STALL_CYCLES_UCHE"/> - <value value="6" name="A7XX_PERF_SP_STALL_CYCLES_RB"/> - <value value="7" name="A7XX_PERF_SP_NON_EXECUTION_CYCLES"/> - <value value="8" name="A7XX_PERF_SP_WAVE_CONTEXTS"/> - <value value="9" name="A7XX_PERF_SP_WAVE_CONTEXT_CYCLES"/> - <value value="10" name="A7XX_PERF_SP_STAGE_WAVE_CYCLES"/> - <value value="11" name="A7XX_PERF_SP_STAGE_WAVE_SAMPLES"/> - <value value="12" name="A7XX_PERF_SP_VS_STAGE_WAVE_CYCLES"/> - <value value="13" name="A7XX_PERF_SP_VS_STAGE_WAVE_SAMPLES"/> - <value value="14" name="A7XX_PERF_SP_FS_STAGE_DURATION_CYCLES"/> - <value value="15" name="A7XX_PERF_SP_VS_STAGE_DURATION_CYCLES"/> - <value value="16" name="A7XX_PERF_SP_WAVE_CTRL_CYCLES"/> - <value value="17" name="A7XX_PERF_SP_WAVE_LOAD_CYCLES"/> - <value value="18" name="A7XX_PERF_SP_WAVE_EMIT_CYCLES"/> - <value value="19" name="A7XX_PERF_SP_WAVE_NOP_CYCLES"/> - <value value="20" name="A7XX_PERF_SP_WAVE_WAIT_CYCLES"/> - <value value="21" name="A7XX_PERF_SP_WAVE_FETCH_CYCLES"/> - <value value="22" name="A7XX_PERF_SP_WAVE_IDLE_CYCLES"/> - <value value="23" name="A7XX_PERF_SP_WAVE_END_CYCLES"/> - <value value="24" name="A7XX_PERF_SP_WAVE_LONG_SYNC_CYCLES"/> - <value value="25" name="A7XX_PERF_SP_WAVE_SHORT_SYNC_CYCLES"/> - <value value="26" name="A7XX_PERF_SP_WAVE_JOIN_CYCLES"/> - <value value="27" name="A7XX_PERF_SP_LM_LOAD_INSTRUCTIONS"/> - <value value="28" name="A7XX_PERF_SP_LM_STORE_INSTRUCTIONS"/> - <value value="29" name="A7XX_PERF_SP_LM_ATOMICS"/> - <value value="30" name="A7XX_PERF_SP_GM_LOAD_INSTRUCTIONS"/> - <value value="31" name="A7XX_PERF_SP_GM_STORE_INSTRUCTIONS"/> - <value value="32" name="A7XX_PERF_SP_GM_ATOMICS"/> - <value value="33" name="A7XX_PERF_SP_VS_STAGE_TEX_INSTRUCTIONS"/> - <value value="34" name="A7XX_PERF_SP_VS_STAGE_EFU_INSTRUCTIONS"/> - <value value="35" name="A7XX_PERF_SP_VS_STAGE_FULL_ALU_INSTRUCTIONS"/> - <value value="36" name="A7XX_PERF_SP_VS_STAGE_HALF_ALU_INSTRUCTIONS"/> - <value value="37" name="A7XX_PERF_SP_FS_STAGE_TEX_INSTRUCTIONS"/> - <value value="38" name="A7XX_PERF_SP_FS_STAGE_CFLOW_INSTRUCTIONS"/> - <value value="39" name="A7XX_PERF_SP_FS_STAGE_EFU_INSTRUCTIONS"/> - <value value="40" name="A7XX_PERF_SP_FS_STAGE_FULL_ALU_INSTRUCTIONS"/> - <value value="41" name="A7XX_PERF_SP_FS_STAGE_HALF_ALU_INSTRUCTIONS"/> - <value value="42" name="A7XX_PERF_SP_FS_STAGE_BARY_INSTRUCTIONS"/> - <value value="43" name="A7XX_PERF_SP_VS_INSTRUCTIONS"/> - <value value="44" name="A7XX_PERF_SP_FS_INSTRUCTIONS"/> - <value value="45" name="A7XX_PERF_SP_ADDR_LOCK_COUNT"/> - <value value="46" name="A7XX_PERF_SP_UCHE_READ_TRANS"/> - <value value="47" name="A7XX_PERF_SP_UCHE_WRITE_TRANS"/> - <value value="48" name="A7XX_PERF_SP_EXPORT_VPC_TRANS"/> - <value value="49" name="A7XX_PERF_SP_EXPORT_RB_TRANS"/> - <value value="50" name="A7XX_PERF_SP_PIXELS_KILLED"/> - <value value="51" name="A7XX_PERF_SP_ICL1_REQUESTS"/> - <value value="52" name="A7XX_PERF_SP_ICL1_MISSES"/> - <value value="53" name="A7XX_PERF_SP_HS_INSTRUCTIONS"/> - <value value="54" name="A7XX_PERF_SP_DS_INSTRUCTIONS"/> - <value value="55" name="A7XX_PERF_SP_GS_INSTRUCTIONS"/> - <value value="56" name="A7XX_PERF_SP_CS_INSTRUCTIONS"/> - <value value="57" name="A7XX_PERF_SP_GPR_READ"/> - <value value="58" name="A7XX_PERF_SP_GPR_WRITE"/> - <value value="59" name="A7XX_PERF_SP_FS_STAGE_HALF_EFU_INSTRUCTIONS"/> - <value value="60" name="A7XX_PERF_SP_VS_STAGE_HALF_EFU_INSTRUCTIONS"/> - <value value="61" name="A7XX_PERF_SP_LM_BANK_CONFLICTS"/> - <value value="62" name="A7XX_PERF_SP_TEX_CONTROL_WORKING_CYCLES"/> - <value value="63" name="A7XX_PERF_SP_LOAD_CONTROL_WORKING_CYCLES"/> - <value value="64" name="A7XX_PERF_SP_FLOW_CONTROL_WORKING_CYCLES"/> - <value value="65" name="A7XX_PERF_SP_LM_WORKING_CYCLES"/> - <value value="66" name="A7XX_PERF_SP_DISPATCHER_WORKING_CYCLES"/> - <value value="67" name="A7XX_PERF_SP_SEQUENCER_WORKING_CYCLES"/> - <value value="68" name="A7XX_PERF_SP_LOW_EFFICIENCY_STARVED_BY_TP"/> - <value value="69" name="A7XX_PERF_SP_STARVE_CYCLES_HLSQ"/> - <value value="70" name="A7XX_PERF_SP_NON_EXECUTION_LS_CYCLES"/> - <value value="71" name="A7XX_PERF_SP_WORKING_EU"/> - <value value="72" name="A7XX_PERF_SP_ANY_EU_WORKING"/> - <value value="73" name="A7XX_PERF_SP_WORKING_EU_FS_STAGE"/> - <value value="74" name="A7XX_PERF_SP_ANY_EU_WORKING_FS_STAGE"/> - <value value="75" name="A7XX_PERF_SP_WORKING_EU_VS_STAGE"/> - <value value="76" name="A7XX_PERF_SP_ANY_EU_WORKING_VS_STAGE"/> - <value value="77" name="A7XX_PERF_SP_WORKING_EU_CS_STAGE"/> - <value value="78" name="A7XX_PERF_SP_ANY_EU_WORKING_CS_STAGE"/> - <value value="79" name="A7XX_PERF_SP_GPR_READ_PREFETCH"/> - <value value="80" name="A7XX_PERF_SP_GPR_READ_CONFLICT"/> - <value value="81" name="A7XX_PERF_SP_GPR_WRITE_CONFLICT"/> - <value value="82" name="A7XX_PERF_SP_GM_LOAD_LATENCY_CYCLES"/> - <value value="83" name="A7XX_PERF_SP_GM_LOAD_LATENCY_SAMPLES"/> - <value value="84" name="A7XX_PERF_SP_EXECUTABLE_WAVES"/> - <value value="85" name="A7XX_PERF_SP_ICL1_MISS_FETCH_CYCLES"/> - <value value="86" name="A7XX_PERF_SP_WORKING_EU_LPAC"/> - <value value="87" name="A7XX_PERF_SP_BYPASS_BUSY_CYCLES"/> - <value value="88" name="A7XX_PERF_SP_ANY_EU_WORKING_LPAC"/> - <value value="89" name="A7XX_PERF_SP_WAVE_ALU_CYCLES"/> - <value value="90" name="A7XX_PERF_SP_WAVE_EFU_CYCLES"/> - <value value="91" name="A7XX_PERF_SP_WAVE_INT_CYCLES"/> - <value value="92" name="A7XX_PERF_SP_WAVE_CSP_CYCLES"/> - <value value="93" name="A7XX_PERF_SP_EWAVE_CONTEXTS"/> - <value value="94" name="A7XX_PERF_SP_EWAVE_CONTEXT_CYCLES"/> - <value value="95" name="A7XX_PERF_SP_LPAC_BUSY_CYCLES"/> - <value value="96" name="A7XX_PERF_SP_LPAC_INSTRUCTIONS"/> - <value value="97" name="A7XX_PERF_SP_FS_STAGE_1X_WAVES"/> - <value value="98" name="A7XX_PERF_SP_FS_STAGE_2X_WAVES"/> - <value value="99" name="A7XX_PERF_SP_QUADS"/> - <value value="100" name="A7XX_PERF_SP_CS_INVOCATIONS"/> - <value value="101" name="A7XX_PERF_SP_PIXELS"/> - <value value="102" name="A7XX_PERF_SP_LPAC_DRAWCALLS"/> - <value value="103" name="A7XX_PERF_SP_PI_WORKING_CYCLES"/> - <value value="104" name="A7XX_PERF_SP_WAVE_INPUT_CYCLES"/> - <value value="105" name="A7XX_PERF_SP_WAVE_OUTPUT_CYCLES"/> - <value value="106" name="A7XX_PERF_SP_WAVE_HWAVE_WAIT_CYCLES"/> - <value value="107" name="A7XX_PERF_SP_WAVE_HWAVE_SYNC"/> - <value value="108" name="A7XX_PERF_SP_OUTPUT_3D_PIXELS"/> - <value value="109" name="A7XX_PERF_SP_FULL_ALU_MAD_INSTRUCTIONS"/> - <value value="110" name="A7XX_PERF_SP_HALF_ALU_MAD_INSTRUCTIONS"/> - <value value="111" name="A7XX_PERF_SP_FULL_ALU_MUL_INSTRUCTIONS"/> - <value value="112" name="A7XX_PERF_SP_HALF_ALU_MUL_INSTRUCTIONS"/> - <value value="113" name="A7XX_PERF_SP_FULL_ALU_ADD_INSTRUCTIONS"/> - <value value="114" name="A7XX_PERF_SP_HALF_ALU_ADD_INSTRUCTIONS"/> - <value value="115" name="A7XX_PERF_SP_BARY_FP32_INSTRUCTIONS"/> - <value value="116" name="A7XX_PERF_SP_ALU_GPR_READ_CYCLES"/> - <value value="117" name="A7XX_PERF_SP_ALU_DATA_FORWARDING_CYCLES"/> - <value value="118" name="A7XX_PERF_SP_LM_FULL_CYCLES"/> - <value value="119" name="A7XX_PERF_SP_TEXTURE_FETCH_LATENCY_CYCLES"/> - <value value="120" name="A7XX_PERF_SP_TEXTURE_FETCH_LATENCY_SAMPLES"/> - <value value="121" name="A7XX_PERF_SP_FS_STAGE_PI_TEX_INSTRUCTION"/> - <value value="122" name="A7XX_PERF_SP_RAY_QUERY_INSTRUCTIONS"/> - <value value="123" name="A7XX_PERF_SP_RBRT_KICKOFF_FIBERS"/> - <value value="124" name="A7XX_PERF_SP_RBRT_KICKOFF_DQUADS"/> - <value value="125" name="A7XX_PERF_SP_RTU_BUSY_CYCLES"/> - <value value="126" name="A7XX_PERF_SP_RTU_L0_HITS"/> - <value value="127" name="A7XX_PERF_SP_RTU_L0_MISSES"/> - <value value="128" name="A7XX_PERF_SP_RTU_L0_HIT_ON_MISS"/> - <value value="129" name="A7XX_PERF_SP_RTU_STALL_CYCLES_WAVE_QUEUE"/> - <value value="130" name="A7XX_PERF_SP_RTU_STALL_CYCLES_L0_HIT_QUEUE"/> - <value value="131" name="A7XX_PERF_SP_RTU_STALL_CYCLES_L0_MISS_QUEUE"/> - <value value="132" name="A7XX_PERF_SP_RTU_STALL_CYCLES_L0D_IDX_QUEUE"/> - <value value="133" name="A7XX_PERF_SP_RTU_STALL_CYCLES_L0DATA"/> - <value value="134" name="A7XX_PERF_SP_RTU_STALL_CYCLES_REPLACE_CNT"/> - <value value="135" name="A7XX_PERF_SP_RTU_STALL_CYCLES_MRG_CNT"/> - <value value="136" name="A7XX_PERF_SP_RTU_STALL_CYCLES_UCHE"/> - <value value="137" name="A7XX_PERF_SP_RTU_OPERAND_FETCH_STALL_CYCLES_L0"/> - <value value="138" name="A7XX_PERF_SP_RTU_OPERAND_FETCH_STALL_CYCLES_INS_FIFO"/> - <value value="139" name="A7XX_PERF_SP_RTU_BVH_FETCH_LATENCY_CYCLES"/> - <value value="140" name="A7XX_PERF_SP_RTU_BVH_FETCH_LATENCY_SAMPLES"/> - <value value="141" name="A7XX_PERF_SP_STCHE_MISS_INC_VS"/> - <value value="142" name="A7XX_PERF_SP_STCHE_MISS_INC_FS"/> - <value value="143" name="A7XX_PERF_SP_STCHE_MISS_INC_BV"/> - <value value="144" name="A7XX_PERF_SP_STCHE_MISS_INC_LPAC"/> - <value value="145" name="A7XX_PERF_SP_VGPR_ACTIVE_CONTEXTS"/> - <value value="146" name="A7XX_PERF_SP_PGPR_ALLOC_CONTEXTS"/> - <value value="147" name="A7XX_PERF_SP_VGPR_ALLOC_CONTEXTS"/> - <value value="148" name="A7XX_PERF_SP_RTU_RAY_BOX_INTERSECTIONS"/> - <value value="149" name="A7XX_PERF_SP_RTU_RAY_TRIANGLE_INTERSECTIONS"/> - <value value="150" name="A7XX_PERF_SP_SCH_STALL_CYCLES_RTU"/> -</enum> - -<enum name="a7xx_rb_perfcounter_select"> - <value value="0" name="A7XX_PERF_RB_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_RB_STALL_CYCLES_HLSQ"/> - <value value="2" name="A7XX_PERF_RB_STALL_CYCLES_FIFO0_FULL"/> - <value value="3" name="A7XX_PERF_RB_STALL_CYCLES_FIFO1_FULL"/> - <value value="4" name="A7XX_PERF_RB_STALL_CYCLES_FIFO2_FULL"/> - <value value="5" name="A7XX_PERF_RB_STARVE_CYCLES_SP"/> - <value value="6" name="A7XX_PERF_RB_STARVE_CYCLES_LRZ_TILE"/> - <value value="7" name="A7XX_PERF_RB_STARVE_CYCLES_CCU"/> - <value value="8" name="A7XX_PERF_RB_STARVE_CYCLES_Z_PLANE"/> - <value value="9" name="A7XX_PERF_RB_STARVE_CYCLES_BARY_PLANE"/> - <value value="10" name="A7XX_PERF_RB_Z_WORKLOAD"/> - <value value="11" name="A7XX_PERF_RB_HLSQ_ACTIVE"/> - <value value="12" name="A7XX_PERF_RB_Z_READ"/> - <value value="13" name="A7XX_PERF_RB_Z_WRITE"/> - <value value="14" name="A7XX_PERF_RB_C_READ"/> - <value value="15" name="A7XX_PERF_RB_C_WRITE"/> - <value value="16" name="A7XX_PERF_RB_TOTAL_PASS"/> - <value value="17" name="A7XX_PERF_RB_Z_PASS"/> - <value value="18" name="A7XX_PERF_RB_Z_FAIL"/> - <value value="19" name="A7XX_PERF_RB_S_FAIL"/> - <value value="20" name="A7XX_PERF_RB_BLENDED_FXP_COMPONENTS"/> - <value value="21" name="A7XX_PERF_RB_BLENDED_FP16_COMPONENTS"/> - <value value="22" name="A7XX_PERF_RB_PS_INVOCATIONS"/> - <value value="23" name="A7XX_PERF_RB_2D_ALIVE_CYCLES"/> - <value value="24" name="A7XX_PERF_RB_2D_STALL_CYCLES_A2D"/> - <value value="25" name="A7XX_PERF_RB_2D_STARVE_CYCLES_SRC"/> - <value value="26" name="A7XX_PERF_RB_2D_STARVE_CYCLES_SP"/> - <value value="27" name="A7XX_PERF_RB_2D_STARVE_CYCLES_DST"/> - <value value="28" name="A7XX_PERF_RB_2D_VALID_PIXELS"/> - <value value="29" name="A7XX_PERF_RB_3D_PIXELS"/> - <value value="30" name="A7XX_PERF_RB_BLENDER_WORKING_CYCLES"/> - <value value="31" name="A7XX_PERF_RB_ZPROC_WORKING_CYCLES"/> - <value value="32" name="A7XX_PERF_RB_CPROC_WORKING_CYCLES"/> - <value value="33" name="A7XX_PERF_RB_SAMPLER_WORKING_CYCLES"/> - <value value="34" name="A7XX_PERF_RB_STALL_CYCLES_CCU_COLOR_READ"/> - <value value="35" name="A7XX_PERF_RB_STALL_CYCLES_CCU_COLOR_WRITE"/> - <value value="36" name="A7XX_PERF_RB_STALL_CYCLES_CCU_DEPTH_READ"/> - <value value="37" name="A7XX_PERF_RB_STALL_CYCLES_CCU_DEPTH_WRITE"/> - <value value="38" name="A7XX_PERF_RB_STALL_CYCLES_VPC"/> - <value value="39" name="A7XX_PERF_RB_2D_INPUT_TRANS"/> - <value value="40" name="A7XX_PERF_RB_2D_OUTPUT_RB_DST_TRANS"/> - <value value="41" name="A7XX_PERF_RB_2D_OUTPUT_RB_SRC_TRANS"/> - <value value="42" name="A7XX_PERF_RB_BLENDED_FP32_COMPONENTS"/> - <value value="43" name="A7XX_PERF_RB_COLOR_PIX_TILES"/> - <value value="44" name="A7XX_PERF_RB_STALL_CYCLES_CCU"/> - <value value="45" name="A7XX_PERF_RB_EARLY_Z_ARB3_GRANT"/> - <value value="46" name="A7XX_PERF_RB_LATE_Z_ARB3_GRANT"/> - <value value="47" name="A7XX_PERF_RB_EARLY_Z_SKIP_GRANT"/> - <value value="48" name="A7XX_PERF_RB_VRS_1x1_QUADS"/> - <value value="49" name="A7XX_PERF_RB_VRS_2x1_QUADS"/> - <value value="50" name="A7XX_PERF_RB_VRS_1x2_QUADS"/> - <value value="51" name="A7XX_PERF_RB_VRS_2x2_QUADS"/> - <value value="52" name="A7XX_PERF_RB_VRS_4x2_QUADS"/> - <value value="53" name="A7XX_PERF_RB_VRS_4x4_QUADS"/> -</enum> - -<enum name="a7xx_vsc_perfcounter_select"> - <value value="0" name="A7XX_PERF_VSC_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_VSC_WORKING_CYCLES"/> - <value value="2" name="A7XX_PERF_VSC_STALL_CYCLES_UCHE"/> - <value value="3" name="A7XX_PERF_VSC_EOT_NUM"/> - <value value="4" name="A7XX_PERF_VSC_INPUT_TILES"/> -</enum> - -<enum name="a7xx_ccu_perfcounter_select"> - <value value="0" name="A7XX_PERF_CCU_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_CCU_STALL_CYCLES_RB_DEPTH_RETURN"/> - <value value="2" name="A7XX_PERF_CCU_STALL_CYCLES_RB_COLOR_RETURN"/> - <value value="3" name="A7XX_PERF_CCU_DEPTH_BLOCKS"/> - <value value="4" name="A7XX_PERF_CCU_COLOR_BLOCKS"/> - <value value="5" name="A7XX_PERF_CCU_DEPTH_BLOCK_HIT"/> - <value value="6" name="A7XX_PERF_CCU_COLOR_BLOCK_HIT"/> - <value value="7" name="A7XX_PERF_CCU_PARTIAL_BLOCK_READ"/> - <value value="8" name="A7XX_PERF_CCU_GMEM_READ"/> - <value value="9" name="A7XX_PERF_CCU_GMEM_WRITE"/> - <value value="10" name="A7XX_PERF_CCU_2D_RD_REQ"/> - <value value="11" name="A7XX_PERF_CCU_2D_WR_REQ"/> - <value value="12" name="A7XX_PERF_CCU_UBWC_COLOR_BLOCKS_CONCURRENT"/> - <value value="13" name="A7XX_PERF_CCU_UBWC_DEPTH_BLOCKS_CONCURRENT"/> - <value value="14" name="A7XX_PERF_CCU_COLOR_RESOLVE_DROPPED"/> - <value value="15" name="A7XX_PERF_CCU_DEPTH_RESOLVE_DROPPED"/> - <value value="16" name="A7XX_PERF_CCU_COLOR_RENDER_CONCURRENT"/> - <value value="17" name="A7XX_PERF_CCU_DEPTH_RENDER_CONCURRENT"/> - <value value="18" name="A7XX_PERF_CCU_COLOR_RESOLVE_AFTER_RENDER"/> - <value value="19" name="A7XX_PERF_CCU_DEPTH_RESOLVE_AFTER_RENDER"/> - <value value="20" name="A7XX_PERF_CCU_GMEM_EXTRA_DEPTH_READ"/> - <value value="21" name="A7XX_PERF_CCU_GMEM_COLOR_READ_4AA"/> - <value value="22" name="A7XX_PERF_CCU_GMEM_COLOR_READ_4AA_FULL"/> -</enum> - -<enum name="a7xx_lrz_perfcounter_select"> - <value value="0" name="A7XX_PERF_LRZ_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_LRZ_STARVE_CYCLES_RAS"/> - <value value="2" name="A7XX_PERF_LRZ_STALL_CYCLES_RB"/> - <value value="3" name="A7XX_PERF_LRZ_STALL_CYCLES_VSC"/> - <value value="4" name="A7XX_PERF_LRZ_STALL_CYCLES_VPC"/> - <value value="5" name="A7XX_PERF_LRZ_STALL_CYCLES_FLAG_PREFETCH"/> - <value value="6" name="A7XX_PERF_LRZ_STALL_CYCLES_UCHE"/> - <value value="7" name="A7XX_PERF_LRZ_LRZ_READ"/> - <value value="8" name="A7XX_PERF_LRZ_LRZ_WRITE"/> - <value value="9" name="A7XX_PERF_LRZ_READ_LATENCY"/> - <value value="10" name="A7XX_PERF_LRZ_MERGE_CACHE_UPDATING"/> - <value value="11" name="A7XX_PERF_LRZ_PRIM_KILLED_BY_MASKGEN"/> - <value value="12" name="A7XX_PERF_LRZ_PRIM_KILLED_BY_LRZ"/> - <value value="13" name="A7XX_PERF_LRZ_VISIBLE_PRIM_AFTER_LRZ"/> - <value value="14" name="A7XX_PERF_LRZ_FULL_8X8_TILES"/> - <value value="15" name="A7XX_PERF_LRZ_PARTIAL_8X8_TILES"/> - <value value="16" name="A7XX_PERF_LRZ_TILE_KILLED"/> - <value value="17" name="A7XX_PERF_LRZ_TOTAL_PIXEL"/> - <value value="18" name="A7XX_PERF_LRZ_VISIBLE_PIXEL_AFTER_LRZ"/> - <value value="19" name="A7XX_PERF_LRZ_FEEDBACK_ACCEPT"/> - <value value="20" name="A7XX_PERF_LRZ_FEEDBACK_DISCARD"/> - <value value="21" name="A7XX_PERF_LRZ_FEEDBACK_STALL"/> - <value value="22" name="A7XX_PERF_LRZ_STALL_CYCLES_RB_ZPLANE"/> - <value value="23" name="A7XX_PERF_LRZ_STALL_CYCLES_RB_BPLANE"/> - <value value="24" name="A7XX_PERF_LRZ_RAS_MASK_TRANS"/> - <value value="25" name="A7XX_PERF_LRZ_STALL_CYCLES_MVC"/> - <value value="26" name="A7XX_PERF_LRZ_TILE_KILLED_BY_IMAGE_VRS"/> - <value value="27" name="A7XX_PERF_LRZ_TILE_KILLED_BY_Z"/> -</enum> - -<enum name="a7xx_cmp_perfcounter_select"> - <value value="0" name="A7XX_PERF_CMPDECMP_STALL_CYCLES_ARB"/> - <value value="1" name="A7XX_PERF_CMPDECMP_VBIF_LATENCY_CYCLES"/> - <value value="2" name="A7XX_PERF_CMPDECMP_VBIF_LATENCY_SAMPLES"/> - <value value="3" name="A7XX_PERF_CMPDECMP_VBIF_READ_DATA_CCU"/> - <value value="4" name="A7XX_PERF_CMPDECMP_VBIF_WRITE_DATA_CCU"/> - <value value="5" name="A7XX_PERF_CMPDECMP_VBIF_READ_REQUEST"/> - <value value="6" name="A7XX_PERF_CMPDECMP_VBIF_WRITE_REQUEST"/> - <value value="7" name="A7XX_PERF_CMPDECMP_VBIF_READ_DATA"/> - <value value="8" name="A7XX_PERF_CMPDECMP_VBIF_WRITE_DATA"/> - <value value="9" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG1_COUNT"/> - <value value="10" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG2_COUNT"/> - <value value="11" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG3_COUNT"/> - <value value="12" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG4_COUNT"/> - <value value="13" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG5_COUNT"/> - <value value="14" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG6_COUNT"/> - <value value="15" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG8_COUNT"/> - <value value="16" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG1_COUNT"/> - <value value="17" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG2_COUNT"/> - <value value="18" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG3_COUNT"/> - <value value="19" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG4_COUNT"/> - <value value="20" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG5_COUNT"/> - <value value="21" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG6_COUNT"/> - <value value="22" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG8_COUNT"/> - <value value="23" name="A7XX_PERF_CMPDECMP_VBIF_READ_DATA_UCHE_CH0"/> - <value value="24" name="A7XX_PERF_CMPDECMP_VBIF_READ_DATA_UCHE_CH1"/> - <value value="25" name="A7XX_PERF_CMPDECMP_VBIF_WRITE_DATA_UCHE"/> - <value value="26" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG0_COUNT"/> - <value value="27" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG0_COUNT"/> - <value value="28" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAGALPHA_COUNT"/> - <value value="29" name="A7XX_PERF_CMPDECMP_RESOLVE_EVENTS"/> - <value value="30" name="A7XX_PERF_CMPDECMP_CONCURRENT_RESOLVE_EVENTS"/> - <value value="31" name="A7XX_PERF_CMPDECMP_DROPPED_CLEAR_EVENTS"/> - <value value="32" name="A7XX_PERF_CMPDECMP_ST_BLOCKS_CONCURRENT"/> - <value value="33" name="A7XX_PERF_CMPDECMP_LRZ_ST_BLOCKS_CONCURRENT"/> - <value value="34" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG0_COUNT"/> - <value value="35" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG1_COUNT"/> - <value value="36" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG2_COUNT"/> - <value value="37" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG3_COUNT"/> - <value value="38" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG4_COUNT"/> - <value value="39" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG5_COUNT"/> - <value value="40" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG6_COUNT"/> - <value value="41" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG8_COUNT"/> - <value value="42" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG0_COUNT"/> - <value value="43" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG1_COUNT"/> - <value value="44" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG2_COUNT"/> - <value value="45" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG3_COUNT"/> - <value value="46" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG4_COUNT"/> - <value value="47" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG5_COUNT"/> - <value value="48" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG6_COUNT"/> - <value value="49" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG8_COUNT"/> -</enum> - -<enum name="a7xx_gbif_perfcounter_select"> - <value value="0" name="A7XX_PERF_GBIF_RESERVED_0"/> - <value value="1" name="A7XX_PERF_GBIF_RESERVED_1"/> - <value value="2" name="A7XX_PERF_GBIF_RESERVED_2"/> - <value value="3" name="A7XX_PERF_GBIF_RESERVED_3"/> - <value value="4" name="A7XX_PERF_GBIF_RESERVED_4"/> - <value value="5" name="A7XX_PERF_GBIF_RESERVED_5"/> - <value value="6" name="A7XX_PERF_GBIF_RESERVED_6"/> - <value value="7" name="A7XX_PERF_GBIF_RESERVED_7"/> - <value value="8" name="A7XX_PERF_GBIF_RESERVED_8"/> - <value value="9" name="A7XX_PERF_GBIF_RESERVED_9"/> - <value value="10" name="A7XX_PERF_GBIF_AXI0_READ_REQUESTS_TOTAL"/> - <value value="11" name="A7XX_PERF_GBIF_AXI1_READ_REQUESTS_TOTAL"/> - <value value="12" name="A7XX_PERF_GBIF_RESERVED_12"/> - <value value="13" name="A7XX_PERF_GBIF_RESERVED_13"/> - <value value="14" name="A7XX_PERF_GBIF_RESERVED_14"/> - <value value="15" name="A7XX_PERF_GBIF_RESERVED_15"/> - <value value="16" name="A7XX_PERF_GBIF_RESERVED_16"/> - <value value="17" name="A7XX_PERF_GBIF_RESERVED_17"/> - <value value="18" name="A7XX_PERF_GBIF_RESERVED_18"/> - <value value="19" name="A7XX_PERF_GBIF_RESERVED_19"/> - <value value="20" name="A7XX_PERF_GBIF_RESERVED_20"/> - <value value="21" name="A7XX_PERF_GBIF_RESERVED_21"/> - <value value="22" name="A7XX_PERF_GBIF_AXI0_WRITE_REQUESTS_TOTAL"/> - <value value="23" name="A7XX_PERF_GBIF_AXI1_WRITE_REQUESTS_TOTAL"/> - <value value="24" name="A7XX_PERF_GBIF_RESERVED_24"/> - <value value="25" name="A7XX_PERF_GBIF_RESERVED_25"/> - <value value="26" name="A7XX_PERF_GBIF_RESERVED_26"/> - <value value="27" name="A7XX_PERF_GBIF_RESERVED_27"/> - <value value="28" name="A7XX_PERF_GBIF_RESERVED_28"/> - <value value="29" name="A7XX_PERF_GBIF_RESERVED_29"/> - <value value="30" name="A7XX_PERF_GBIF_RESERVED_30"/> - <value value="31" name="A7XX_PERF_GBIF_RESERVED_31"/> - <value value="32" name="A7XX_PERF_GBIF_RESERVED_32"/> - <value value="33" name="A7XX_PERF_GBIF_RESERVED_33"/> - <value value="34" name="A7XX_PERF_GBIF_AXI0_READ_DATA_BEATS_TOTAL"/> - <value value="35" name="A7XX_PERF_GBIF_AXI1_READ_DATA_BEATS_TOTAL"/> - <value value="36" name="A7XX_PERF_GBIF_RESERVED_36"/> - <value value="37" name="A7XX_PERF_GBIF_RESERVED_37"/> - <value value="38" name="A7XX_PERF_GBIF_RESERVED_38"/> - <value value="39" name="A7XX_PERF_GBIF_RESERVED_39"/> - <value value="40" name="A7XX_PERF_GBIF_RESERVED_40"/> - <value value="41" name="A7XX_PERF_GBIF_RESERVED_41"/> - <value value="42" name="A7XX_PERF_GBIF_RESERVED_42"/> - <value value="43" name="A7XX_PERF_GBIF_RESERVED_43"/> - <value value="44" name="A7XX_PERF_GBIF_RESERVED_44"/> - <value value="45" name="A7XX_PERF_GBIF_RESERVED_45"/> - <value value="46" name="A7XX_PERF_GBIF_AXI0_WRITE_DATA_BEATS_TOTAL"/> - <value value="47" name="A7XX_PERF_GBIF_AXI1_WRITE_DATA_BEATS_TOTAL"/> - <value value="48" name="A7XX_PERF_GBIF_RESERVED_48"/> - <value value="49" name="A7XX_PERF_GBIF_RESERVED_49"/> - <value value="50" name="A7XX_PERF_GBIF_RESERVED_50"/> - <value value="51" name="A7XX_PERF_GBIF_RESERVED_51"/> - <value value="52" name="A7XX_PERF_GBIF_RESERVED_52"/> - <value value="53" name="A7XX_PERF_GBIF_RESERVED_53"/> - <value value="54" name="A7XX_PERF_GBIF_RESERVED_54"/> - <value value="55" name="A7XX_PERF_GBIF_RESERVED_55"/> - <value value="56" name="A7XX_PERF_GBIF_RESERVED_56"/> - <value value="57" name="A7XX_PERF_GBIF_RESERVED_57"/> - <value value="58" name="A7XX_PERF_GBIF_RESERVED_58"/> - <value value="59" name="A7XX_PERF_GBIF_RESERVED_59"/> - <value value="60" name="A7XX_PERF_GBIF_RESERVED_60"/> - <value value="61" name="A7XX_PERF_GBIF_RESERVED_61"/> - <value value="62" name="A7XX_PERF_GBIF_RESERVED_62"/> - <value value="63" name="A7XX_PERF_GBIF_RESERVED_63"/> - <value value="64" name="A7XX_PERF_GBIF_RESERVED_64"/> - <value value="65" name="A7XX_PERF_GBIF_RESERVED_65"/> - <value value="66" name="A7XX_PERF_GBIF_RESERVED_66"/> - <value value="67" name="A7XX_PERF_GBIF_RESERVED_67"/> - <value value="68" name="A7XX_PERF_GBIF_CYCLES_CH0_HELD_OFF_RD_ALL"/> - <value value="69" name="A7XX_PERF_GBIF_CYCLES_CH1_HELD_OFF_RD_ALL"/> - <value value="70" name="A7XX_PERF_GBIF_CYCLES_CH0_HELD_OFF_WR_ALL"/> - <value value="71" name="A7XX_PERF_GBIF_CYCLES_CH1_HELD_OFF_WR_ALL"/> - <value value="72" name="A7XX_PERF_GBIF_AXI_CH0_REQUEST_HELD_OFF"/> - <value value="73" name="A7XX_PERF_GBIF_AXI_CH1_REQUEST_HELD_OFF"/> - <value value="74" name="A7XX_PERF_GBIF_AXI_REQUEST_HELD_OFF"/> - <value value="75" name="A7XX_PERF_GBIF_AXI_CH0_WRITE_DATA_HELD_OFF"/> - <value value="76" name="A7XX_PERF_GBIF_AXI_CH1_WRITE_DATA_HELD_OFF"/> - <value value="77" name="A7XX_PERF_GBIF_AXI_ALL_WRITE_DATA_HELD_OFF"/> - <value value="78" name="A7XX_PERF_GBIF_AXI_ALL_READ_BEATS"/> - <value value="79" name="A7XX_PERF_GBIF_AXI_ALL_WRITE_BEATS"/> - <value value="80" name="A7XX_PERF_GBIF_AXI_ALL_BEATS"/> -</enum> - -<enum name="a7xx_ufc_perfcounter_select"> - <value value="0" name="A7XX_PERF_UFC_BUSY_CYCLES"/> - <value value="1" name="A7XX_PERF_UFC_READ_DATA_VBIF"/> - <value value="2" name="A7XX_PERF_UFC_WRITE_DATA_VBIF"/> - <value value="3" name="A7XX_PERF_UFC_READ_REQUEST_VBIF"/> - <value value="4" name="A7XX_PERF_UFC_WRITE_REQUEST_VBIF"/> - <value value="5" name="A7XX_PERF_UFC_LRZ_FILTER_HIT"/> - <value value="6" name="A7XX_PERF_UFC_LRZ_FILTER_MISS"/> - <value value="7" name="A7XX_PERF_UFC_CRE_FILTER_HIT"/> - <value value="8" name="A7XX_PERF_UFC_CRE_FILTER_MISS"/> - <value value="9" name="A7XX_PERF_UFC_SP_FILTER_HIT"/> - <value value="10" name="A7XX_PERF_UFC_SP_FILTER_MISS"/> - <value value="11" name="A7XX_PERF_UFC_SP_REQUESTS"/> - <value value="12" name="A7XX_PERF_UFC_TP_FILTER_HIT"/> - <value value="13" name="A7XX_PERF_UFC_TP_FILTER_MISS"/> - <value value="14" name="A7XX_PERF_UFC_TP_REQUESTS"/> - <value value="15" name="A7XX_PERF_UFC_MAIN_HIT_LRZ_PREFETCH"/> - <value value="16" name="A7XX_PERF_UFC_MAIN_HIT_CRE_PREFETCH"/> - <value value="17" name="A7XX_PERF_UFC_MAIN_HIT_SP_PREFETCH"/> - <value value="18" name="A7XX_PERF_UFC_MAIN_HIT_TP_PREFETCH"/> - <value value="19" name="A7XX_PERF_UFC_MAIN_HIT_UBWC_READ"/> - <value value="20" name="A7XX_PERF_UFC_MAIN_HIT_UBWC_WRITE"/> - <value value="21" name="A7XX_PERF_UFC_MAIN_MISS_LRZ_PREFETCH"/> - <value value="22" name="A7XX_PERF_UFC_MAIN_MISS_CRE_PREFETCH"/> - <value value="23" name="A7XX_PERF_UFC_MAIN_MISS_SP_PREFETCH"/> - <value value="24" name="A7XX_PERF_UFC_MAIN_MISS_TP_PREFETCH"/> - <value value="25" name="A7XX_PERF_UFC_MAIN_MISS_UBWC_READ"/> - <value value="26" name="A7XX_PERF_UFC_MAIN_MISS_UBWC_WRITE"/> - <value value="27" name="A7XX_PERF_UFC_UBWC_READ_UFC_TRANS"/> - <value value="28" name="A7XX_PERF_UFC_UBWC_WRITE_UFC_TRANS"/> - <value value="29" name="A7XX_PERF_UFC_STALL_CYCLES_GBIF_CMD"/> - <value value="30" name="A7XX_PERF_UFC_STALL_CYCLES_GBIF_RDATA"/> - <value value="31" name="A7XX_PERF_UFC_STALL_CYCLES_GBIF_WDATA"/> - <value value="32" name="A7XX_PERF_UFC_STALL_CYCLES_UBWC_WR_FLAG"/> - <value value="33" name="A7XX_PERF_UFC_STALL_CYCLES_UBWC_FLAG_RTN"/> - <value value="34" name="A7XX_PERF_UFC_STALL_CYCLES_UBWC_EVENT"/> - <value value="35" name="A7XX_PERF_UFC_LRZ_PREFETCH_STALLED_CYCLES"/> - <value value="36" name="A7XX_PERF_UFC_CRE_PREFETCH_STALLED_CYCLES"/> - <value value="37" name="A7XX_PERF_UFC_SPTP_PREFETCH_STALLED_CYCLES"/> - <value value="38" name="A7XX_PERF_UFC_UBWC_RD_STALLED_CYCLES"/> - <value value="39" name="A7XX_PERF_UFC_UBWC_WR_STALLED_CYCLES"/> - <value value="40" name="A7XX_PERF_UFC_PREFETCH_STALLED_CYCLES"/> - <value value="41" name="A7XX_PERF_UFC_EVICTION_STALLED_CYCLES"/> - <value value="42" name="A7XX_PERF_UFC_LOCK_STALLED_CYCLES"/> - <value value="43" name="A7XX_PERF_UFC_MISS_LATENCY_CYCLES"/> - <value value="44" name="A7XX_PERF_UFC_MISS_LATENCY_SAMPLES"/> - <value value="45" name="A7XX_PERF_UFC_UBWC_REQ_STALLED_CYCLES"/> - <value value="46" name="A7XX_PERF_UFC_TP_HINT_TAG_MISS"/> - <value value="47" name="A7XX_PERF_UFC_TP_HINT_TAG_HIT_RDY"/> - <value value="48" name="A7XX_PERF_UFC_TP_HINT_TAG_HIT_NRDY"/> - <value value="49" name="A7XX_PERF_UFC_TP_HINT_IS_FCLEAR"/> - <value value="50" name="A7XX_PERF_UFC_TP_HINT_IS_ALPHA0"/> - <value value="51" name="A7XX_PERF_UFC_SP_L1_FILTER_HIT"/> - <value value="52" name="A7XX_PERF_UFC_SP_L1_FILTER_MISS"/> - <value value="53" name="A7XX_PERF_UFC_SP_L1_FILTER_REQUESTS"/> - <value value="54" name="A7XX_PERF_UFC_TP_L1_TAG_HIT_RDY"/> - <value value="55" name="A7XX_PERF_UFC_TP_L1_TAG_HIT_NRDY"/> - <value value="56" name="A7XX_PERF_UFC_TP_L1_TAG_MISS"/> - <value value="57" name="A7XX_PERF_UFC_TP_L1_FILTER_REQUESTS"/> -</enum> - <domain name="A6XX" width="32" prefix="variant" varset="chip"> <bitset name="A6XX_RBBM_INT_0_MASK" inline="no" varset="chip"> <bitfield name="RBBM_GPU_IDLE" pos="0" type="boolean"/> @@ -2278,29 +86,134 @@ to upconvert to 32b float internally? <bitfield name="CP_ILLEGAL_INSTR_ERROR_BV" pos="17" type="boolean" variants="A7XX-"/> </bitset> + <bitset name="A8XX_CP_GLOBAL_INT_MASK" inline="no" varset="chip"> + <bitfield name="HWFAULTBR" pos="0" type="boolean"/> + <bitfield name="HWFAULTBV" pos="1" type="boolean"/> + <bitfield name="HWFAULTLPAC" pos="2" type="boolean"/> + <bitfield name="HWFAULTAQE0" pos="3" type="boolean"/> + <bitfield name="HWFAULTAQE1" pos="4" type="boolean"/> + <bitfield name="HWFAULTDDEBR" pos="5" type="boolean"/> + <bitfield name="HWFAULTDDEBV" pos="6" type="boolean"/> + <bitfield name="SWFAULTBR" pos="16" type="boolean"/> + <bitfield name="SWFAULTBV" pos="17" type="boolean"/> + <bitfield name="SWFAULTLPAC" pos="18" type="boolean"/> + <bitfield name="SWFAULTAQE0" pos="19" type="boolean"/> + <bitfield name="SWFAULTAQE1" pos="20" type="boolean"/> + <bitfield name="SWFAULTDDEBR" pos="21" type="boolean"/> + <bitfield name="SWFAULTDDEBV" pos="22" type="boolean"/> + </bitset> + + <bitset name="A8XX_CP_INTERRUPT_STATUS_MASK_PIPE" inline="no" varset="chip"> + <bitfield name="CSFRBWRAP" pos="0" type="boolean"/> + <bitfield name="CSFIB1WRAP" pos="1" type="boolean"/> + <bitfield name="CSFIB2WRAP" pos="2" type="boolean"/> + <bitfield name="CSFIB3WRAP" pos="3" type="boolean"/> + <bitfield name="CSFSDSWRAP" pos="4" type="boolean"/> + <bitfield name="CSFMRBWRAP" pos="5" type="boolean"/> + <bitfield name="CSFVSDWRAP" pos="6" type="boolean"/> + <bitfield name="OPCODEERROR" pos="8" type="boolean"/> + <bitfield name="VSDPARITYERROR" pos="9" type="boolean"/> + <bitfield name="REGISTERPROTECTIONERROR" pos="10" type="boolean"/> + <bitfield name="ILLEGALINSTRUCTION" pos="11" type="boolean"/> + <bitfield name="SMMUFAULT" pos="12" type="boolean"/> + <bitfield name="VBIFRESPCLIENT" pos="13" type="boolean"/> + <bitfield name="VBIFRESPTYPE" pos="19" type="boolean"/> + <bitfield name="VBIFRESPREAD" pos="21" type="boolean"/> + <bitfield name="VBIFRESP" pos="22" type="boolean"/> + <bitfield name="RTWROVF" pos="23" type="boolean"/> + <bitfield name="LRZRTWROVF" pos="24" type="boolean"/> + <bitfield name="LRZRTREFCNTOVF" pos="25" type="boolean"/> + <bitfield name="LRZRTCLRRESMISS" pos="26" type="boolean"/> + </bitset> + + <bitset name="A8XX_CP_HW_FAULT_STATUS_MASK_PIPE" inline="no" varset="chip"> + <bitfield name="CSFRBFAULT" pos="0" type="boolean"/> + <bitfield name="CSFIB1FAULT" pos="1" type="boolean"/> + <bitfield name="CSFIB2FAULT" pos="2" type="boolean"/> + <bitfield name="CSFIB3FAULT" pos="3" type="boolean"/> + <bitfield name="CSFSDSFAULT" pos="4" type="boolean"/> + <bitfield name="CSFMRBFAULT" pos="5" type="boolean"/> + <bitfield name="CSFVSDFAULT" pos="6" type="boolean"/> + <bitfield name="SQEREADBURSTOVF" pos="8" type="boolean"/> + <bitfield name="EVENTENGINEOVF" pos="9" type="boolean"/> + <bitfield name="UCODEERROR" pos="10" type="boolean"/> + </bitset> + <reg64 offset="0x0800" name="CP_RB_BASE"/> <reg32 offset="0x0802" name="CP_RB_CNTL"/> + <reg32 offset="0x0803" name="CP_RB_RPTR_WR" variants="A7XX-"/> <reg64 offset="0x0804" name="CP_RB_RPTR_ADDR"/> <reg32 offset="0x0806" name="CP_RB_RPTR"/> <reg32 offset="0x0807" name="CP_RB_WPTR"/> - <reg32 offset="0x0808" name="CP_SQE_CNTL"/> - <reg32 offset="0x0812" name="CP_CP2GMU_STATUS"> + <reg32 offset="0x0808" name="CP_RB_RPTR_ADDR_BV" variants="A8XX-"/> + <reg32 offset="0x080a" name="CP_RB_RPTR_BV" variants="A8XX-"/> + <reg64 offset="0x080b" name="CP_RB_BASE_LPAC" variants="A8XX-"/> + <reg32 offset="0x080d" name="CP_RB_CNTL_LPAC" variants="A8XX-"/> + <reg32 offset="0x080e" name="CP_RB_RPTR_WR_LPAC" variants="A8XX-"/> + <reg64 offset="0x080f" name="CP_RB_RPTR_ADDR_LPAC" variants="A8XX-"/> + <reg32 offset="0x0811" name="CP_RB_RPTR_LPAC" variants="A8XX-"/> + <reg32 offset="0x0812" name="CP_RB_WPTR_LPAC" variants="A8XX-"/> + <reg32 offset="0x0814" name="CP_SMMU_STREAM_ID_LPAC" variants="A8XX-"/> + <reg32 offset="0x0808" name="CP_SQE_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x0815" name="CP_SQE_CNTL" variants="A8XX-"/> + <reg64 offset="0x0816" name="CP_SQE_INSTR_BASE" variants="A8XX-"/> + <reg64 offset="0x0818" name="CP_AQE_INSTR_BASE_0" variants="A8XX-"/> + <reg64 offset="0x081a" name="CP_AQE_INSTR_BASE_1" variants="A8XX-"/> + <reg32 offset="0x0812" name="CP_CP2GMU_STATUS" variants="A6XX-A7XX"> + <!-- Note, layout defined by microcode --> + <bitfield name="IFPC" pos="0" type="boolean"/> + </reg32> + <reg32 offset="0x0822" name="CP_CP2GMU_STATUS" variants="A8XX-"> <bitfield name="IFPC" pos="0" type="boolean"/> </reg32> - <reg32 offset="0x0821" name="CP_HW_FAULT"/> - <reg32 offset="0x0823" name="CP_INTERRUPT_STATUS" type="A6XX_CP_INT"/> - <reg32 offset="0x0824" name="CP_PROTECT_STATUS"/> - <reg32 offset="0x0825" name="CP_STATUS_1"/> - <reg64 offset="0x0830" name="CP_SQE_INSTR_BASE"/> - <reg32 offset="0x0840" name="CP_MISC_CNTL"/> - <reg32 offset="0x0844" name="CP_APRIV_CNTL"> + <reg32 offset="0x0821" name="CP_HW_FAULT" variants="A6XX-A7XX"/> + <reg32 offset="0x0823" name="CP_INTERRUPT_STATUS" type="A6XX_CP_INT" variants="A6XX-A7XX"/> + + <bitset name="a6xx_cp_protect_status" inline="yes"> + <bitfield name="ADDR" low="0" high="17"/> + <bitfield name="READ" pos="20" type="boolean"/> + <bitfield name="CP_HALTED" pos="21" type="boolean"/> + <bitfield name="ACCESS_VIOLATION" pos="22" type="boolean"/> + </bitset> + + <reg32 offset="0x0824" name="CP_PROTECT_STATUS" type="a6xx_cp_protect_status" variants="A6XX-A7XX"/> + <reg32 offset="0x084f" name="CP_PROTECT_STATUS_PIPE" type="a6xx_cp_protect_status" variants="A8XX-"/> + <reg32 offset="0x0825" name="CP_STATUS_1" variants="A6XX-A7XX"/> + + <reg32 offset="0x0825" name="CP_SEMAPHORE_REG_0" variants="A8XX-"/> + <array offset="0x082a" name="CP_SCRATCH_GLOBAL" stride="1" length="4" variants="A8XX-"> + <reg32 offset="0x0" name="REG"/> + </array> + <array offset="0x0830" name="CP_SCRATCH_PIPE" stride="1" length="5" variants="A8XX-"> + <reg32 offset="0x0" name="REG"/> + </array> + + <reg32 offset="0x0840" name="CP_RL_ERROR_DETAILS_0" variants="A8XX-"/> + <reg32 offset="0x0841" name="CP_RL_ERROR_DETAILS_1" variants="A8XX-"/> + + <reg64 offset="0x0830" name="CP_SQE_INSTR_BASE" variants="A6XX-A7XX"/> + <reg32 offset="0x0840" name="CP_MISC_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x084c" name="CP_MISC_CNTL" variants="A8XX-"/> + + <reg32 offset="0x08b0" name="CP_SQE_ICACHE_CNTL_PIPE" variants="A8XX-"/> + <reg32 offset="0x08b1" name="CP_SQE_DCACHE_CNTL_PIPE" variants="A8XX-"/> + <reg32 offset="0x08b3" name="CP_HW_FAULT_STATUS_PIPE" variants="A8XX-"/> + <reg32 offset="0x08b4" name="CP_HW_FAULT_STATUS_MASK_PIPE" variants="A8XX-"/> + <reg32 offset="0x08b5" name="CP_INTERRUPT_STATUS_GLOBAL" type="A8XX_CP_GLOBAL_INT_MASK" variants="A8XX-"/> + <reg32 offset="0x08b6" name="CP_INTERRUPT_STATUS_MASK_GLOBAL" type="A8XX_CP_GLOBAL_INT_MASK" variants="A8XX-"/> + <reg32 offset="0x08b7" name="CP_INTERRUPT_STATUS_PIPE" type="A8XX_CP_INTERRUPT_STATUS_MASK_PIPE" variants="A8XX-"/> + <reg32 offset="0x08b8" name="CP_INTERRUPT_STATUS_MASK_PIPE" variants="A8XX-"/> + <reg32 offset="0x08b9" name="CP_PIPE_STATUS_PIPE" variants="A8XX-"/> + <reg32 offset="0x08ba" name="CP_GPU_BATCH_ID_PIPE" variants="A8XX-"/> + <reg32 offset="0x08bb" name="CP_SQE_STATUS_PIPE" variants="A8XX-"/> + + <bitset name="a6xx_cp_apriv_cntl" inline="yes"> <!-- Crashdumper writes --> <bitfield pos="6" name="CDWRITE" type="boolean"/> <!-- Crashdumper reads --> <bitfield pos="5" name="CDREAD" type="boolean"/> - - <!-- 4 is unknown --> - + <!-- CP Scratch reg copy to mem --> + <bitfield pos="4" name="SCRATCHWT" type="boolean"/> <!-- RPTR shadow writes --> <bitfield pos="3" name="RBRPWB" type="boolean"/> <!-- Memory accesses from PM4 packets in the ringbuffer --> @@ -2309,11 +222,16 @@ to upconvert to 32b float internally? <bitfield pos="1" name="RBFETCH" type="boolean"/> <!-- Instruction cache fetches --> <bitfield pos="0" name="ICACHE" type="boolean"/> - </reg32> + </bitset> + + <reg32 offset="0x0844" name="CP_APRIV_CNTL" type="a6xx_cp_apriv_cntl" variants="A6XX-A7XX"/> + <reg32 offset="0x084d" name="CP_APRIV_CNTL_PIPE" type="a6xx_cp_apriv_cntl" variants="A8XX-"/> + <!-- Preemptions taking longer than this threshold increment PERF_CP_LONG_PREEMPTIONS: --> - <reg32 offset="0x08C0" name="CP_PREEMPT_THRESHOLD"/> + <reg32 offset="0x08c0" name="CP_PREEMPT_THRESHOLD" variants="A6XX-A7XX"/> + <reg32 offset="0x08ec" name="CP_PREEMPT_THRESHOLD" variants="A8XX-"/> <!-- all the threshold values seem to be in units of quad-dwords: --> - <reg32 offset="0x08C1" name="CP_ROQ_THRESHOLDS_1"> + <reg32 offset="0x08c1" name="CP_ROQ_THRESHOLDS_1" variants="A6XX"> <doc> b0..7 identifies where MRB data starts (and RB data ends) b8.15 identifies where VSD data starts (and MRB data ends) @@ -2325,7 +243,7 @@ to upconvert to 32b float internally? <bitfield name="IB1_START" low="16" high="23" shr="2"/> <bitfield name="IB2_START" low="24" high="31" shr="2"/> </reg32> - <reg32 offset="0x08C2" name="CP_ROQ_THRESHOLDS_2"> + <reg32 offset="0x08c2" name="CP_ROQ_THRESHOLDS_2" variants="A6XX"> <doc> low bits identify where CP_SET_DRAW_STATE stateobj processing starts (and IB2 data ends). I'm guessing @@ -2341,175 +259,293 @@ to upconvert to 32b float internally? <!-- total ROQ size: --> <bitfield name="ROQ_SIZE" low="16" high="31" shr="2"/> </reg32> - <reg32 offset="0x08C3" name="CP_MEM_POOL_SIZE"/> - <reg32 offset="0x0841" name="CP_CHICKEN_DBG"/> - <reg32 offset="0x0842" name="CP_ADDR_MODE_CNTL" type="a5xx_address_mode"/> - <reg32 offset="0x0843" name="CP_DBG_ECO_CNTL"/> - <reg32 offset="0x084F" name="CP_PROTECT_CNTL"> + <reg32 offset="0x08C3" name="CP_MEM_POOL_SIZE" variants="A6XX"/> + <reg32 offset="0x0841" name="CP_CHICKEN_DBG" variants="A6XX-A7XX"/> + <reg32 offset="0x08b2" name="CP_CHICKEN_DBG_PIPE" variants="A8XX-"/> + <reg32 offset="0x0842" name="CP_ADDR_MODE_CNTL" type="a5xx_address_mode" variants="A6XX"/> + <reg32 offset="0x0843" name="CP_DBG_ECO_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x084b" name="CP_DBG_ECO_CNTL" variants="A8XX-"/> + + <bitset name="a6xx_cp_protect_cntl" inline="yes"> <bitfield pos="3" name="LAST_SPAN_INF_RANGE" type="boolean"/> <bitfield pos="1" name="ACCESS_FAULT_ON_VIOL_EN" type="boolean"/> <bitfield pos="0" name="ACCESS_PROT_EN" type="boolean"/> - </reg32> + </bitset> - <array offset="0x0883" name="CP_SCRATCH" stride="1" length="8"> + <reg32 offset="0x084f" name="CP_PROTECT_CNTL" type="a6xx_cp_protect_cntl" variants="A6XX-A7XX"/> + <bitset name="a8xx_cp_protect_cntl" inline="yes"> + <bitfield name="HALT_SQE_RANGE" low="16" high="31"/> + <bitfield name="LAST_SPAN_INF_RANGE" pos="3" type="boolean"/> + <bitfield name="ACCESS_FAULT_ON_VIOL_EN" pos="1" type="boolean"/> + <bitfield name="ACCESS_PROT_EN" pos="0" type="boolean"/> + </bitset> + + <reg32 offset="0x084e" name="CP_PROTECT_CNTL_PIPE" type="a8xx_cp_protect_cntl" variants="A8XX-"/> + + <array offset="0x0883" name="CP_SCRATCH" stride="1" length="8" variants="A6XX-A7XX"> <reg32 offset="0x0" name="REG" type="uint"/> </array> - <array offset="0x0850" name="CP_PROTECT" stride="1" length="32"> + <array offset="0x0850" name="CP_PROTECT" stride="1" length="32" variants="A6XX-A7XX"> + <reg32 offset="0x0" name="REG" type="a6x_cp_protect"/> + </array> + <array offset="0x0850" name="CP_PROTECT_GLOBAL" stride="1" length="64" variants="A8XX-"> + <reg32 offset="0x0" name="REG" type="a6x_cp_protect"/> + </array> + <array offset="0x08a0" name="CP_PROTECT_PIPE" stride="1" length="16" variants="A8XX-"> <reg32 offset="0x0" name="REG" type="a6x_cp_protect"/> </array> - <reg32 offset="0x08A0" name="CP_CONTEXT_SWITCH_CNTL"> + <bitset name="a6xx_cp_context_switch_cntl" inline="yes"> <bitfield name="STOP" pos="0" type="boolean"/> <bitfield name="LEVEL" low="6" high="7"/> <bitfield name="USES_GMEM" pos="8" type="boolean"/> <bitfield name="SKIP_SAVE_RESTORE" pos="9" type="boolean"/> - </reg32> - <reg64 offset="0x08A1" name="CP_CONTEXT_SWITCH_SMMU_INFO"/> - <reg64 offset="0x08A3" name="CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR"/> - <reg64 offset="0x08A5" name="CP_CONTEXT_SWITCH_PRIV_SECURE_RESTORE_ADDR"/> - <reg64 offset="0x08A7" name="CP_CONTEXT_SWITCH_NON_PRIV_RESTORE_ADDR"/> - <reg32 offset="0x08ab" name="CP_CONTEXT_SWITCH_LEVEL_STATUS" variants="A7XX-"/> - <array offset="0x08D0" name="CP_PERFCTR_CP_SEL" stride="1" length="14"/> - <array offset="0x08e0" name="CP_BV_PERFCTR_CP_SEL" stride="1" length="7" variants="A7XX-"/> - <reg64 offset="0x0900" name="CP_CRASH_SCRIPT_BASE"/> - <reg32 offset="0x0902" name="CP_CRASH_DUMP_CNTL"/> - <reg32 offset="0x0903" name="CP_CRASH_DUMP_STATUS"/> - <reg32 offset="0x0908" name="CP_SQE_STAT_ADDR"/> - <reg32 offset="0x0909" name="CP_SQE_STAT_DATA"/> - <reg32 offset="0x090A" name="CP_DRAW_STATE_ADDR"/> - <reg32 offset="0x090B" name="CP_DRAW_STATE_DATA"/> - <reg32 offset="0x090C" name="CP_ROQ_DBG_ADDR"/> - <reg32 offset="0x090D" name="CP_ROQ_DBG_DATA"/> - <reg32 offset="0x090E" name="CP_MEM_POOL_DBG_ADDR"/> - <reg32 offset="0x090F" name="CP_MEM_POOL_DBG_DATA"/> - <reg32 offset="0x0910" name="CP_SQE_UCODE_DBG_ADDR"/> - <reg32 offset="0x0911" name="CP_SQE_UCODE_DBG_DATA"/> - <reg64 offset="0x0928" name="CP_IB1_BASE"/> - <reg32 offset="0x092A" name="CP_IB1_REM_SIZE"/> - <reg64 offset="0x092B" name="CP_IB2_BASE"/> - <reg32 offset="0x092D" name="CP_IB2_REM_SIZE"/> + </bitset> + + <reg32 offset="0x08a0" name="CP_CONTEXT_SWITCH_CNTL" type="a6xx_cp_context_switch_cntl" variants="A6XX-A7XX"/> + <reg32 offset="0x08c0" name="CP_CONTEXT_SWITCH_CNTL" type="a6xx_cp_context_switch_cntl" variants="A8XX-"/> + + <reg64 offset="0x08a1" name="CP_CONTEXT_SWITCH_SMMU_INFO" variants="A6XX-A7XX"/> + <reg64 offset="0x08a3" name="CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR" variants="A6XX-A7XX"/> + <reg64 offset="0x08a5" name="CP_CONTEXT_SWITCH_PRIV_SECURE_RESTORE_ADDR" variants="A6XX-A7XX"/> + <reg64 offset="0x08a7" name="CP_CONTEXT_SWITCH_NON_PRIV_RESTORE_ADDR" variants="A6XX-A7XX"/> + <reg32 offset="0x08ab" name="CP_CONTEXT_SWITCH_LEVEL_STATUS" variants="A7XX"/> + + <reg64 offset="0x08c1" name="CP_CONTEXT_SWITCH_SMMU_INFO" variants="A8XX-"/> + <reg64 offset="0x08c3" name="CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR" variants="A8XX-"/> + <reg64 offset="0x08c5" name="CP_CONTEXT_SWITCH_PRIV_SECURE_RESTORE_ADDR" variants="A8XX-"/> + <reg64 offset="0x08c7" name="CP_CONTEXT_SWITCH_NON_PRIV_RESTORE_ADDR" variants="A8XX-"/> + <reg32 offset="0x08cb" name="CP_CONTEXT_SWITCH_LEVEL_STATUS" variants="A8XX-"/> + + <array offset="0x08d0" name="CP_PERFCTR_CP_SEL" stride="1" length="14" variants="A6XX-A7XX"/> + <array offset="0x08d0" name="CP_PERFCTR_CP_SEL" stride="1" length="21" variants="A8XX-"/> + <array offset="0x08e0" name="CP_BV_PERFCTR_CP_SEL" stride="1" length="7" variants="A7XX"/> + <reg64 offset="0x0900" name="CP_CRASH_DUMP_SCRIPT_BASE" variants="A6XX-A7XX"/> + <reg32 offset="0x0902" name="CP_CRASH_DUMP_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x0903" name="CP_CRASH_DUMP_STATUS" variants="A6XX-A7XX"/> + <reg64 offset="0x0842" name="CP_CRASH_DUMP_SCRIPT_BASE" variants="A8XX-"/> + <reg32 offset="0x0844" name="CP_CRASH_DUMP_CNTL" variants="A8XX-"/> + <reg32 offset="0x0845" name="CP_CRASH_DUMP_STATUS" variants="A8XX-"/> + <reg32 offset="0x0908" name="CP_SQE_STAT_ADDR" variants="A6XX-A7XX"/> + <reg32 offset="0x0909" name="CP_SQE_STAT_DATA" variants="A6XX-A7XX"/> + <reg32 offset="0x090a" name="CP_DRAW_STATE_ADDR" variants="A6XX-A7XX"/> + <reg32 offset="0x090b" name="CP_DRAW_STATE_DATA" variants="A6XX-A7XX"/> + <reg32 offset="0x090c" name="CP_ROQ_DBG_ADDR" variants="A6XX-A7XX"/> + <reg32 offset="0x090d" name="CP_ROQ_DBG_DATA" variants="A6XX-A7XX"/> + <reg32 offset="0x090e" name="CP_MEM_POOL_DBG_ADDR" variants="A6XX-A7XX"/> + <reg32 offset="0x090f" name="CP_MEM_POOL_DBG_DATA" variants="A6XX-A7XX"/> + <reg32 offset="0x0910" name="CP_SQE_UCODE_DBG_ADDR" variants="A6XX-A7XX"/> + <reg32 offset="0x0911" name="CP_SQE_UCODE_DBG_DATA" variants="A6XX-A7XX"/> + + <reg32 offset="0x08f0" name="CP_SQE_STAT_ADDR_PIPE" variants="A8XX-"/> + <reg32 offset="0x08f1" name="CP_SQE_STAT_DATA_PIPE" variants="A8XX-"/> + <reg32 offset="0x08f2" name="CP_DRAW_STATE_ADDR_PIPE" variants="A8XX-"/> + <reg32 offset="0x08f3" name="CP_DRAW_STATE_DATA_PIPE" variants="A8XX-"/> + <reg32 offset="0x08f4" name="CP_ROQ_DBG_ADDR_PIPE" variants="A8XX-"/> + <reg32 offset="0x08f5" name="CP_ROQ_DBG_DATA_PIPE" variants="A8XX-"/> + <reg32 offset="0x08f6" name="CP_MEM_POOL_DBG_ADDR_PIPE" variants="A8XX-"/> + <reg32 offset="0x08f7" name="CP_MEM_POOL_DBG_DATA_PIPE" variants="A8XX-"/> + <reg32 offset="0x08f8" name="CP_SQE_UCODE_DBG_ADDR_PIPE" variants="A8XX-"/> + <reg32 offset="0x08f9" name="CP_SQE_UCODE_DBG_DATA_PIPE" variants="A8XX-"/> + <reg32 offset="0x08fa" name="CP_RESOURCE_TABLE_DBG_ADDR_BV" variants="A8XX-"/> + <reg32 offset="0x08fb" name="CP_RESOURCE_TABLE_DBG_DATA_BV" variants="A8XX-"/> + <reg32 offset="0x08fc" name="CP_FIFO_DBG_ADDR_LPAC" variants="A8XX-"/> + <reg32 offset="0x08fd" name="CP_FIFO_DBG_DATA_LPAC" variants="A8XX-"/> + <reg32 offset="0x08fe" name="CP_FIFO_DBG_ADDR_DDE_PIPE" variants="A8XX-"/> + <reg32 offset="0x08ff" name="CP_FIFO_DBG_DATA_DDE_PIPE" variants="A8XX-"/> + + <reg32 offset="0x0b00" name="CP_SLICE_MEM_POOL_DBG_ADDR_PIPE" variants="A8XX-"/> + <reg32 offset="0x0b01" name="CP_SLICE_MEM_POOL_DBG_DATA_PIPE" variants="A8XX-"/> + <reg32 offset="0x0b93" name="CP_SLICE_CHICKEN_DBG_PIPE" variants="A8XX-"/> + + <reg64 offset="0x0928" name="CP_IB1_BASE" variants="A6XX-A7XX"/> + <reg32 offset="0x092a" name="CP_IB1_REM_SIZE" variants="A6XX-A7XX"/> + <reg64 offset="0x092b" name="CP_IB2_BASE" variants="A6XX-A7XX"/> + <reg32 offset="0x092d" name="CP_IB2_REM_SIZE" variants="A6XX-A7XX"/> <!-- SDS == CP_SET_DRAW_STATE: --> - <reg64 offset="0x092e" name="CP_SDS_BASE"/> - <reg32 offset="0x0930" name="CP_SDS_REM_SIZE"/> + <reg64 offset="0x092e" name="CP_SDS_BASE" variants="A6XX-A7XX"/> + <reg32 offset="0x0930" name="CP_SDS_REM_SIZE" variants="A6XX-A7XX"/> <!-- MRB == MEM_READ_ADDR/$addr in SQE firmware --> - <reg64 offset="0x0931" name="CP_MRB_BASE"/> - <reg32 offset="0x0933" name="CP_MRB_REM_SIZE"/> + <reg64 offset="0x0931" name="CP_MRB_BASE" variants="A6XX-A7XX"/> + <reg32 offset="0x0933" name="CP_MRB_REM_SIZE" variants="A6XX-A7XX"/> <!-- VSD == Visibility Stream Decode This is used by CP to read the draw stream and skip empty draws --> - <reg64 offset="0x0934" name="CP_VSD_BASE"/> - - <bitset name="a6xx_roq_stat" inline="yes"> + <reg64 offset="0x0934" name="CP_VSD_BASE" variants="A6XX-A7XX"/> + + <reg64 offset="0x0900" name="CP_IB1_BASE" variants="A8XX-"/> + <reg32 offset="0x0902" name="CP_IB1_REM_SIZE" variants="A8XX-"/> + <reg32 offset="0x0903" name="CP_IB1_INIT_SIZE" variants="A8XX-"/> + <reg64 offset="0x0904" name="CP_IB2_BASE" variants="A8XX-"/> + <reg32 offset="0x0906" name="CP_IB2_REM_SIZE" variants="A8XX-"/> + <reg32 offset="0x0907" name="CP_IB2_INIT_SIZE" variants="A8XX-"/> + <reg64 offset="0x0908" name="CP_IB3_BASE" variants="A8XX-"/> + <reg32 offset="0x090a" name="CP_IB3_REM_SIZE" variants="A8XX-"/> + <reg32 offset="0x090b" name="CP_IB3_INIT_SIZE" variants="A8XX-"/> + <reg64 offset="0x090c" name="CP_SDS_BASE" variants="A8XX-"/> + <reg32 offset="0x090e" name="CP_SDS_REM_SIZE" variants="A8XX-"/> + <reg32 offset="0x090f" name="CP_SDS_INIT_SIZE" variants="A8XX-"/> + <reg64 offset="0x0910" name="CP_MRB_BASE" variants="A8XX-"/> + <reg32 offset="0x0912" name="CP_MRB_REM_SIZE" variants="A8XX-"/> + <reg32 offset="0x0913" name="CP_MRB_INIT_SIZE" variants="A8XX-"/> + <reg64 offset="0x0914" name="CP_VSD_BASE" variants="A8XX-"/> + <reg32 offset="0x0916" name="CP_VSD_REM_SIZE" variants="A8XX-"/> + <reg32 offset="0x0917" name="CP_VSD_INIT_SIZE" variants="A8XX-"/> + + <bitset name="a6xx_roq_status" inline="yes"> <bitfield name="RPTR" low="0" high="9"/> <bitfield name="WPTR" low="16" high="25"/> </bitset> - <reg32 offset="0x0939" name="CP_ROQ_RB_STAT" type="a6xx_roq_stat"/> - <reg32 offset="0x093a" name="CP_ROQ_IB1_STAT" type="a6xx_roq_stat"/> - <reg32 offset="0x093b" name="CP_ROQ_IB2_STAT" type="a6xx_roq_stat"/> - <reg32 offset="0x093c" name="CP_ROQ_SDS_STAT" type="a6xx_roq_stat"/> - <reg32 offset="0x093d" name="CP_ROQ_MRB_STAT" type="a6xx_roq_stat"/> - <reg32 offset="0x093e" name="CP_ROQ_VSD_STAT" type="a6xx_roq_stat"/> - - <reg32 offset="0x0943" name="CP_IB1_DWORDS"/> - <reg32 offset="0x0944" name="CP_IB2_DWORDS"/> - <reg32 offset="0x0945" name="CP_SDS_DWORDS"/> - <reg32 offset="0x0946" name="CP_MRB_DWORDS"/> - <reg32 offset="0x0947" name="CP_VSD_DWORDS"/> - - <reg32 offset="0x0948" name="CP_ROQ_AVAIL_RB"> - <doc>number of remaining dwords incl current dword being consumed?</doc> - <bitfield name="REM" low="16" high="31"/> - </reg32> - <reg32 offset="0x0949" name="CP_ROQ_AVAIL_IB1"> + <reg32 offset="0x0939" name="CP_ROQ_RB_STATUS" type="a6xx_roq_status" variants="A6XX-A7XX"/> + <reg32 offset="0x093a" name="CP_ROQ_IB1_STATUS" type="a6xx_roq_status" variants="A6XX-A7XX"/> + <reg32 offset="0x093b" name="CP_ROQ_IB2_STATUS" type="a6xx_roq_status" variants="A6XX-A7XX"/> + <reg32 offset="0x093c" name="CP_ROQ_SDS_STATUS" type="a6xx_roq_status" variants="A6XX-A7XX"/> + <reg32 offset="0x093d" name="CP_ROQ_MRB_STATUS" type="a6xx_roq_status" variants="A6XX-A7XX"/> + <reg32 offset="0x093e" name="CP_ROQ_VSD_STATUS" type="a6xx_roq_status" variants="A6XX-A7XX"/> + + <reg32 offset="0x0920" name="CP_ROQ_RB_STATUS" type="a6xx_roq_status" variants="A8XX-"/> + <reg32 offset="0x0921" name="CP_ROQ_IB1_STATUS" type="a6xx_roq_status" variants="A8XX-"/> + <reg32 offset="0x0922" name="CP_ROQ_IB2_STATUS" type="a6xx_roq_status" variants="A8XX-"/> + <reg32 offset="0x0923" name="CP_ROQ_IB3_STATUS" type="a6xx_roq_status" variants="A8XX-"/> + <reg32 offset="0x0924" name="CP_ROQ_SDS_STATUS" type="a6xx_roq_status" variants="A8XX-"/> + <reg32 offset="0x0925" name="CP_ROQ_MRB_STATUS" type="a6xx_roq_status" variants="A8XX-"/> + <reg32 offset="0x0926" name="CP_ROQ_VSD_STATUS" type="a6xx_roq_status" variants="A8XX-"/> + + <reg32 offset="0x0943" name="CP_IB1_INIT_SIZE" variants="A6XX-A7XX"/> + <reg32 offset="0x0944" name="CP_IB2_INIT_SIZE" variants="A6XX-A7XX"/> + <reg32 offset="0x0945" name="CP_SDS_INIT_SIZE" variants="A6XX-A7XX"/> + <reg32 offset="0x0946" name="CP_MRB_INIT_SIZE" variants="A6XX-A7XX"/> + <reg32 offset="0x0947" name="CP_VSD_INIT_SIZE" variants="A6XX-A7XX"/> + + <bitset name="a6xx_cp_roq_avail" inline="yes"> <doc>number of remaining dwords incl current dword being consumed?</doc> <bitfield name="REM" low="16" high="31"/> - </reg32> - <reg32 offset="0x094a" name="CP_ROQ_AVAIL_IB2"> + </bitset> + + <reg32 offset="0x0948" name="CP_ROQ_AVAIL_RB" type="a6xx_cp_roq_avail" variants="A6XX-A7XX"/> + <reg32 offset="0x0949" name="CP_ROQ_AVAIL_IB1" type="a6xx_cp_roq_avail" variants="A6XX-A7XX"/> + <reg32 offset="0x094a" name="CP_ROQ_AVAIL_IB2" type="a6xx_cp_roq_avail" variants="A6XX-A7XX"/> + <reg32 offset="0x094b" name="CP_ROQ_AVAIL_SDS" type="a6xx_cp_roq_avail" variants="A6XX-A7XX"/> + <reg32 offset="0x094c" name="CP_ROQ_AVAIL_MRB" type="a6xx_cp_roq_avail" variants="A6XX-A7XX"/> + <reg32 offset="0x094d" name="CP_ROQ_AVAIL_VSD" type="a6xx_cp_roq_avail" variants="A6XX-A7XX"/> + + <reg32 offset="0x0918" name="CP_ROQ_AVAIL_RB" type="a6xx_cp_roq_avail" variants="A8XX-"/> + <reg32 offset="0x0919" name="CP_ROQ_AVAIL_IB1" type="a6xx_cp_roq_avail" variants="A8XX-"/> + <reg32 offset="0x091a" name="CP_ROQ_AVAIL_IB2" type="a6xx_cp_roq_avail" variants="A8XX-"/> + <reg32 offset="0x091b" name="CP_ROQ_AVAIL_IB3" type="a6xx_cp_roq_avail" variants="A8XX-"/> + <reg32 offset="0x091c" name="CP_ROQ_AVAIL_SDS" type="a6xx_cp_roq_avail" variants="A8XX-"/> + <reg32 offset="0x091d" name="CP_ROQ_AVAIL_MRB" type="a6xx_cp_roq_avail" variants="A8XX-"/> + <reg32 offset="0x091e" name="CP_ROQ_AVAIL_VSD" type="a6xx_cp_roq_avail" variants="A8XX-"/> + + <bitset name="a7xx_aperture_cntl" inline="yes"> + <bitfield name="PIPE" low="12" high="13" type="adreno_pipe"/> + <bitfield name="CLUSTER" low="8" high="10" type="a7xx_cluster"/> + <bitfield name="CONTEXT" low="4" high="5"/> + </bitset> + <reg64 offset="0x0980" name="CP_ALWAYS_ON_COUNTER" variants="A6XX-A7XX"/> + <reg64 offset="0x0982" name="CP_ALWAYS_ON_CONTEXT" variants="A6XX-A7XX"/> + <reg64 offset="0x08e7" name="CP_ALWAYS_ON_COUNTER" variants="A8XX-"/> + <reg64 offset="0x08e9" name="CP_ALWAYS_ON_CONTEXT" variants="A8XX-"/> + <reg32 offset="0x098d" name="CP_AHB_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x0838" name="CP_AHB_CNTL" variants="A8XX-"/> + <reg32 offset="0x0A00" name="CP_APERTURE_CNTL_HOST" variants="A6XX"/> + <reg32 offset="0x0A00" name="CP_APERTURE_CNTL_HOST" type="a7xx_aperture_cntl" variants="A7XX"/> + <reg32 offset="0x0A01" name="CP_APERTURE_CNTL_SQE" variants="A6XX"/> + <reg32 offset="0x0A03" name="CP_APERTURE_CNTL_CD" variants="A6XX"/> + <reg32 offset="0x0A03" name="CP_APERTURE_CNTL_CD" type="a7xx_aperture_cntl" variants="A7XX"/> + + <array offset="0x0a9c" name="CP_RESERVED_REG" stride="1" length="4" variants="A7XX"/> + <array offset="0x0958" name="CP_RESERVED_REG" stride="1" length="4" variants="A8XX-"/> + + <bitset name="a8xx_aperture_cntl" inline="yes"> + <bitfield name="CONTEXTID3D" low="4" high="5"/> + <bitfield name="CLUSTERID" low="8" high="11"/> + <bitfield name="PIPEID" low="12" high="15"/> + <bitfield name="SLICEID" low="16" high="18"/> + <bitfield name="USESLICEID" pos="23" type="boolean"/> + </bitset> + + <reg32 offset="0x081c" name="CP_APERTURE_CNTL_HOST" type="a8xx_aperture_cntl" variants="A8XX-"/> + <reg32 offset="0x081d" name="CP_APERTURE_CNTL_GMU" type="a8xx_aperture_cntl" variants="A8XX-"/> + <reg32 offset="0x081e" name="CP_APERTURE_CNTL_CD" type="a8xx_aperture_cntl" variants="A8XX-"/> + + <reg32 offset="0x0a61" name="CP_BV_PROTECT_STATUS" variants="A7XX"/> + <reg32 offset="0x0a64" name="CP_BV_HW_FAULT" variants="A7XX"/> + <reg32 offset="0x0a66" name="CP_BV_RB_RPTR" variants="A7XX"/> + <reg64 offset="0x0a6d" name="CP_BV_IB1_BASE" variants="A7XX"/> + <reg32 offset="0x0a70" name="CP_BV_IB1_REM_SIZE" variants="A7XX"/> + <reg64 offset="0x0a71" name="CP_BV_IB2_BASE" variants="A7XX"/> + <reg32 offset="0x0a74" name="CP_BV_IB2_REM_SIZE" variants="A7XX"/> + <reg32 offset="0x0a81" name="CP_BV_DRAW_STATE_ADDR" variants="A7XX"/> + <reg32 offset="0x0a82" name="CP_BV_DRAW_STATE_DATA" variants="A7XX"/> + <reg32 offset="0x0a83" name="CP_BV_ROQ_DBG_ADDR" variants="A7XX"/> + <reg32 offset="0x0a84" name="CP_BV_ROQ_DBG_DATA" variants="A7XX"/> + <reg32 offset="0x0a85" name="CP_BV_SQE_UCODE_DBG_ADDR" variants="A7XX"/> + <reg32 offset="0x0a86" name="CP_BV_SQE_UCODE_DBG_DATA" variants="A7XX"/> + <reg32 offset="0x0a87" name="CP_BV_SQE_STAT_ADDR" variants="A7XX"/> + <reg32 offset="0x0a88" name="CP_BV_SQE_STAT_DATA" variants="A7XX"/> + + <reg32 offset="0x0a8f" name="CP_BV_ROQ_AVAIL_RB" variants="A7XX"> <doc>number of remaining dwords incl current dword being consumed?</doc> <bitfield name="REM" low="16" high="31"/> </reg32> - <reg32 offset="0x094b" name="CP_ROQ_AVAIL_SDS"> + <reg32 offset="0x0a90" name="CP_BV_ROQ_AVAIL_IB1" variants="A7XX"> <doc>number of remaining dwords incl current dword being consumed?</doc> <bitfield name="REM" low="16" high="31"/> </reg32> - <reg32 offset="0x094c" name="CP_ROQ_AVAIL_MRB"> - <doc>number of dwords that have already been read but haven't been consumed by $addr</doc> - <bitfield name="REM" low="16" high="31"/> - </reg32> - <reg32 offset="0x094d" name="CP_ROQ_AVAIL_VSD"> + <reg32 offset="0x0a91" name="CP_BV_ROQ_AVAIL_IB2" variants="A7XX"> <doc>number of remaining dwords incl current dword being consumed?</doc> <bitfield name="REM" low="16" high="31"/> </reg32> - <bitset name="a7xx_aperture_cntl" inline="yes"> - <bitfield name="PIPE" low="12" high="13" type="a7xx_pipe"/> - <bitfield name="CLUSTER" low="8" high="10" type="a7xx_cluster"/> - <bitfield name="CONTEXT" low="4" high="5"/> - </bitset> - <reg64 offset="0x0980" name="CP_ALWAYS_ON_COUNTER"/> - <reg32 offset="0x098D" name="CP_AHB_CNTL"/> - <reg32 offset="0x0A00" name="CP_APERTURE_CNTL_HOST" variants="A6XX"/> - <reg32 offset="0x0A00" name="CP_APERTURE_CNTL_HOST" type="a7xx_aperture_cntl" variants="A7XX-"/> - <reg32 offset="0x0A03" name="CP_APERTURE_CNTL_CD" variants="A6XX"/> - <reg32 offset="0x0A03" name="CP_APERTURE_CNTL_CD" type="a7xx_aperture_cntl" variants="A7XX-"/> - - <reg32 offset="0x0a61" name="CP_BV_PROTECT_STATUS" variants="A7XX-"/> - <reg32 offset="0x0a64" name="CP_BV_HW_FAULT" variants="A7XX-"/> - <reg32 offset="0x0a81" name="CP_BV_DRAW_STATE_ADDR" variants="A7XX-"/> - <reg32 offset="0x0a82" name="CP_BV_DRAW_STATE_DATA" variants="A7XX-"/> - <reg32 offset="0x0a83" name="CP_BV_ROQ_DBG_ADDR" variants="A7XX-"/> - <reg32 offset="0x0a84" name="CP_BV_ROQ_DBG_DATA" variants="A7XX-"/> - <reg32 offset="0x0a85" name="CP_BV_SQE_UCODE_DBG_ADDR" variants="A7XX-"/> - <reg32 offset="0x0a86" name="CP_BV_SQE_UCODE_DBG_DATA" variants="A7XX-"/> - <reg32 offset="0x0a87" name="CP_BV_SQE_STAT_ADDR" variants="A7XX-"/> - <reg32 offset="0x0a88" name="CP_BV_SQE_STAT_DATA" variants="A7XX-"/> - <reg32 offset="0x0a96" name="CP_BV_MEM_POOL_DBG_ADDR" variants="A7XX-"/> - <reg32 offset="0x0a97" name="CP_BV_MEM_POOL_DBG_DATA" variants="A7XX-"/> - <reg64 offset="0x0a98" name="CP_BV_RB_RPTR_ADDR" variants="A7XX-"/> - - <reg32 offset="0x0a9a" name="CP_RESOURCE_TBL_DBG_ADDR" variants="A7XX-"/> - <reg32 offset="0x0a9b" name="CP_RESOURCE_TBL_DBG_DATA" variants="A7XX-"/> - <reg32 offset="0x0ad0" name="CP_BV_APRIV_CNTL" variants="A7XX-"/> - <reg32 offset="0x0ada" name="CP_BV_CHICKEN_DBG" variants="A7XX-"/> - - <reg32 offset="0x0b0a" name="CP_LPAC_DRAW_STATE_ADDR" variants="A7XX-"/> - <reg32 offset="0x0b0b" name="CP_LPAC_DRAW_STATE_DATA" variants="A7XX-"/> - <reg32 offset="0x0b0c" name="CP_LPAC_ROQ_DBG_ADDR" variants="A7XX-"/> - <reg32 offset="0x0b27" name="CP_SQE_AC_UCODE_DBG_ADDR" variants="A7XX-"/> - <reg32 offset="0x0b28" name="CP_SQE_AC_UCODE_DBG_DATA" variants="A7XX-"/> - <reg32 offset="0x0b29" name="CP_SQE_AC_STAT_ADDR" variants="A7XX-"/> - <reg32 offset="0x0b2a" name="CP_SQE_AC_STAT_DATA" variants="A7XX-"/> - - <reg32 offset="0x0b31" name="CP_LPAC_APRIV_CNTL" variants="A7XX-"/> - <reg32 offset="0x0B34" name="CP_LPAC_PROG_FIFO_SIZE"/> - <reg32 offset="0x0b35" name="CP_LPAC_ROQ_DBG_DATA" variants="A7XX-"/> - <reg32 offset="0x0b36" name="CP_LPAC_FIFO_DBG_DATA" variants="A7XX-"/> - <reg32 offset="0x0b40" name="CP_LPAC_FIFO_DBG_ADDR" variants="A7XX-"/> - <reg32 offset="0x0b81" name="CP_LPAC_SQE_CNTL"/> - <reg64 offset="0x0b82" name="CP_LPAC_SQE_INSTR_BASE"/> - - <reg64 offset="0x0b70" name="CP_AQE_INSTR_BASE_0" variants="A7XX-"/> - <reg64 offset="0x0b72" name="CP_AQE_INSTR_BASE_1" variants="A7XX-"/> - <reg32 offset="0x0b78" name="CP_AQE_APRIV_CNTL" variants="A7XX-"/> - - <reg32 offset="0x0ba8" name="CP_AQE_ROQ_DBG_ADDR_0" variants="A7XX-"/> - <reg32 offset="0x0ba9" name="CP_AQE_ROQ_DBG_ADDR_1" variants="A7XX-"/> - <reg32 offset="0x0bac" name="CP_AQE_ROQ_DBG_DATA_0" variants="A7XX-"/> - <reg32 offset="0x0bad" name="CP_AQE_ROQ_DBG_DATA_1" variants="A7XX-"/> - <reg32 offset="0x0bb0" name="CP_AQE_UCODE_DBG_ADDR_0" variants="A7XX-"/> - <reg32 offset="0x0bb1" name="CP_AQE_UCODE_DBG_ADDR_1" variants="A7XX-"/> - <reg32 offset="0x0bb4" name="CP_AQE_UCODE_DBG_DATA_0" variants="A7XX-"/> - <reg32 offset="0x0bb5" name="CP_AQE_UCODE_DBG_DATA_1" variants="A7XX-"/> - <reg32 offset="0x0bb8" name="CP_AQE_STAT_ADDR_0" variants="A7XX-"/> - <reg32 offset="0x0bb9" name="CP_AQE_STAT_ADDR_1" variants="A7XX-"/> - <reg32 offset="0x0bbc" name="CP_AQE_STAT_DATA_0" variants="A7XX-"/> - <reg32 offset="0x0bbd" name="CP_AQE_STAT_DATA_1" variants="A7XX-"/> - - <reg32 offset="0x0C01" name="VSC_ADDR_MODE_CNTL" type="a5xx_address_mode"/> - <reg32 offset="0x0018" name="RBBM_GPR0_CNTL"/> - <reg32 offset="0x0201" name="RBBM_INT_0_STATUS" type="A6XX_RBBM_INT_0_MASK"/> - <reg32 offset="0x0210" name="RBBM_STATUS"> + <reg32 offset="0x0a96" name="CP_BV_MEM_POOL_DBG_ADDR" variants="A7XX"/> + <reg32 offset="0x0a97" name="CP_BV_MEM_POOL_DBG_DATA" variants="A7XX"/> + <reg64 offset="0x0a98" name="CP_BV_RB_RPTR_ADDR" variants="A7XX"/> + + <reg32 offset="0x0a9a" name="CP_RESOURCE_TABLE_DBG_ADDR" variants="A7XX"/> + <reg32 offset="0x0a9b" name="CP_RESOURCE_TABLE_DBG_DATA" variants="A7XX"/> + <reg32 offset="0x0ad0" name="CP_BV_APRIV_CNTL" variants="A7XX"/> + <reg32 offset="0x0ada" name="CP_BV_CHICKEN_DBG" variants="A7XX"/> + + <reg32 offset="0x0b0a" name="CP_LPAC_DRAW_STATE_ADDR" variants="A7XX"/> + <reg32 offset="0x0b0b" name="CP_LPAC_DRAW_STATE_DATA" variants="A7XX"/> + <reg32 offset="0x0b0c" name="CP_LPAC_ROQ_DBG_ADDR" variants="A7XX"/> + <reg32 offset="0x0b27" name="CP_SQE_AC_UCODE_DBG_ADDR" variants="A7XX"/> + <reg32 offset="0x0b28" name="CP_SQE_AC_UCODE_DBG_DATA" variants="A7XX"/> + <reg32 offset="0x0b29" name="CP_SQE_AC_STAT_ADDR" variants="A7XX"/> + <reg32 offset="0x0b2a" name="CP_SQE_AC_STAT_DATA" variants="A7XX"/> + + <reg32 offset="0x0b31" name="CP_LPAC_APRIV_CNTL" variants="A7XX"/> + <reg32 offset="0x0b34" name="CP_LPAC_PROG_FIFO_SIZE" variants="A7XX"/> + <reg32 offset="0x0b35" name="CP_LPAC_ROQ_DBG_DATA" variants="A7XX"/> + <reg32 offset="0x0b36" name="CP_LPAC_FIFO_DBG_DATA" variants="A7XX"/> + <reg32 offset="0x0b40" name="CP_LPAC_FIFO_DBG_ADDR" variants="A7XX"/> + <reg32 offset="0x0b81" name="CP_LPAC_SQE_CNTL" variants="A6XX-A7XX"/> + <reg64 offset="0x0b82" name="CP_LPAC_SQE_INSTR_BASE" variants="A6XX-A7XX"/> + + <reg64 offset="0x0b70" name="CP_AQE_INSTR_BASE_0" variants="A7XX"/> + <reg64 offset="0x0b72" name="CP_AQE_INSTR_BASE_1" variants="A7XX"/> + <reg32 offset="0x0b78" name="CP_AQE_APRIV_CNTL" variants="A7XX"/> + + <reg32 offset="0x0ba8" name="CP_AQE_ROQ_DBG_ADDR_0" variants="A7XX"/> + <reg32 offset="0x0ba9" name="CP_AQE_ROQ_DBG_ADDR_1" variants="A7XX"/> + <reg32 offset="0x0bac" name="CP_AQE_ROQ_DBG_DATA_0" variants="A7XX"/> + <reg32 offset="0x0bad" name="CP_AQE_ROQ_DBG_DATA_1" variants="A7XX"/> + <reg32 offset="0x0bb0" name="CP_AQE_UCODE_DBG_ADDR_0" variants="A7XX"/> + <reg32 offset="0x0bb1" name="CP_AQE_UCODE_DBG_ADDR_1" variants="A7XX"/> + <reg32 offset="0x0bb4" name="CP_AQE_UCODE_DBG_DATA_0" variants="A7XX"/> + <reg32 offset="0x0bb5" name="CP_AQE_UCODE_DBG_DATA_1" variants="A7XX"/> + <reg32 offset="0x0bb8" name="CP_AQE_STAT_ADDR_0" variants="A7XX"/> + <reg32 offset="0x0bb9" name="CP_AQE_STAT_ADDR_1" variants="A7XX"/> + <reg32 offset="0x0bbc" name="CP_AQE_STAT_DATA_0" variants="A7XX"/> + <reg32 offset="0x0bbd" name="CP_AQE_STAT_DATA_1" variants="A7XX"/> + + <reg32 offset="0x0C01" name="VSC_ADDR_MODE_CNTL" type="a5xx_address_mode" variants="A6XX"/> + <reg32 offset="0x0018" name="RBBM_GPR0_CNTL" variants="A6XX"/> + <reg32 offset="0x0201" name="RBBM_INT_0_STATUS" type="A6XX_RBBM_INT_0_MASK" variants="A6XX-A7XX"/> + <reg32 offset="0x006a" name="RBBM_INT_0_STATUS" type="A6XX_RBBM_INT_0_MASK" variants="A8XX-"/> + <reg32 offset="0x0210" name="RBBM_STATUS" variants="A6XX-A7XX"> <bitfield pos="23" name="GPU_BUSY_IGN_AHB" type="boolean"/> <bitfield pos="22" name="GPU_BUSY_IGN_AHB_CP" type="boolean"/> <bitfield pos="21" name="HLSQ_BUSY" type="boolean"/> @@ -2535,22 +571,59 @@ to upconvert to 32b float internally? <bitfield pos="1" name="CP_AHB_BUSY_CP_MASTER" type="boolean"/> <bitfield pos="0" name="CP_AHB_BUSY_CX_MASTER" type="boolean"/> </reg32> - <reg32 offset="0x0211" name="RBBM_STATUS1"/> - <reg32 offset="0x0212" name="RBBM_STATUS2"/> - <reg32 offset="0x0213" name="RBBM_STATUS3"> + <reg32 offset="0x0211" name="RBBM_STATUS1" variants="A6XX-A7XX"/> + <reg32 offset="0x0212" name="RBBM_STATUS2" variants="A6XX-A7XX"/> + <reg32 offset="0x0213" name="RBBM_STATUS3" variants="A6XX-A7XX"> <bitfield pos="24" name="SMMU_STALLED_ON_FAULT" type="boolean"/> </reg32> - <reg32 offset="0x0215" name="RBBM_VBIF_GX_RESET_STATUS"/> - <reg32 offset="0x0260" name="RBBM_CLOCK_MODE_CP" variants="A7XX-"/> - <reg32 offset="0x0284" name="RBBM_CLOCK_MODE_BV_LRZ" variants="A7XX-"/> - <reg32 offset="0x0285" name="RBBM_CLOCK_MODE_BV_GRAS" variants="A7XX-"/> - <reg32 offset="0x0286" name="RBBM_CLOCK_MODE2_GRAS" variants="A7XX-"/> - <reg32 offset="0x0287" name="RBBM_CLOCK_MODE_BV_VFD" variants="A7XX-"/> - <reg32 offset="0x0288" name="RBBM_CLOCK_MODE_BV_GPC" variants="A7XX-"/> + <reg32 offset="0x012" name="RBBM_STATUS" variants="A8XX-"> + <bitfield pos="23" name="GPU_BUSY_IGN_AHB" type="boolean"/> + <bitfield pos="22" name="GPU_BUSY_IGN_AHB_CP" type="boolean"/> + <bitfield pos="21" name="SLICE_BUSY_IGN_CP" type="boolean"/> + <bitfield pos="20" name="CP_SLICE_BUSY" type="boolean"/> + <bitfield pos="19" name="UNSLICE_BUSY_IGN_AHB" type="boolean"/> + <bitfield pos="18" name="UNSLICE_BUSY_IGN_AHB_CP" type="boolean"/> + <bitfield pos="17" name="CP_SLICE_RL_BUSY" type="boolean"/> + <bitfield pos="14" name="UNSLICE_TOP_BUSY" type="boolean"/> + <bitfield pos="13" name="UFC_BUSY" type="boolean"/> + <bitfield pos="12" name="HLSQ_BUSY" type="boolean"/> + <bitfield pos="11" name="VSC_BUSY" type="boolean"/> + <bitfield pos="10" name="UCHE_BUSY" type="boolean"/> + <bitfield pos="9" name="VPC_BUSY" type="boolean"/> + <bitfield pos="8" name="PC_BUSY" type="boolean"/> + <bitfield pos="7" name="CMP_BUSY" type="boolean"/> + <bitfield pos="6" name="DCMP_BUSY" type="boolean"/> + <bitfield pos="5" name="VBIF_GX_BUSY" type="boolean"/> + <bitfield pos="4" name="DBGC_PERF_BUSY" type="boolean"/> + <bitfield pos="3" name="GFX_DBGC_BUSY" type="boolean"/> + <bitfield pos="2" name="CP_BUSY" type="boolean"/> + <bitfield pos="1" name="CP_AHB_BUSY_CP_MASTER" type="boolean"/> + <bitfield pos="0" name="CP_AHB_BUSY_CX_MASTER" type="boolean"/> + </reg32> + <reg32 offset="0x013" name="RBBM_STATUS1" variants="A8XX-"/> + <reg32 offset="0x015" name="RBBM_GFX_STATUS" variants="A8XX-"/> + <reg32 offset="0x016" name="RBBM_GFX_STATUS1" variants="A8XX-"/> + <reg32 offset="0x018" name="RBBM_LPAC_STATUS" variants="A8XX-"/> + <reg32 offset="0x01a" name="RBBM_GFX_BR_STATUS" variants="A8XX-"/> + <reg32 offset="0x01c" name="RBBM_GFX_BV_STATUS" variants="A8XX-"/> + <reg32 offset="0x01e" name="RBBM_MISC_STATUS" variants="A8XX-"> + <bitfield pos="0" name="SMMU_STALLED_ON_FAULT" type="boolean"/> + </reg32> + + <reg32 offset="0x0215" name="RBBM_VBIF_GX_RESET_STATUS" variants="A6XX"/> - <reg32 offset="0x02c0" name="RBBM_SW_FUSE_INT_STATUS" variants="A7XX-"/> - <reg32 offset="0x02c1" name="RBBM_SW_FUSE_INT_MASK" variants="A7XX-"/> + <reg32 offset="0x0260" name="RBBM_CLOCK_MODE_CP" variants="A7XX"/> + <reg32 offset="0x0284" name="RBBM_CLOCK_MODE_BV_LRZ" variants="A7XX"/> + <reg32 offset="0x0285" name="RBBM_CLOCK_MODE_BV_GRAS" variants="A7XX"/> + <reg32 offset="0x0286" name="RBBM_CLOCK_MODE2_GRAS" variants="A7XX"/> + <reg32 offset="0x0287" name="RBBM_CLOCK_MODE_BV_VFD" variants="A7XX"/> + <reg32 offset="0x0288" name="RBBM_CLOCK_MODE_BV_GPC" variants="A7XX"/> + + <reg32 offset="0x02c0" name="RBBM_SW_FUSE_INT_STATUS" variants="A7XX"/> + <reg32 offset="0x02c1" name="RBBM_SW_FUSE_INT_MASK" variants="A7XX"/> + <reg32 offset="0x0071" name="RBBM_SW_FUSE_INT_STATUS" variants="A8XX-"/> + <reg32 offset="0x0072" name="RBBM_SW_FUSE_INT_MASK" variants="A8XX-"/> <array offset="0x0400" name="RBBM_PERFCTR_CP" stride="2" length="14" variants="A6XX"/> <array offset="0x041c" name="RBBM_PERFCTR_RBBM" stride="2" length="4" variants="A6XX"/> @@ -2569,49 +642,96 @@ to upconvert to 32b float internally? <array offset="0x04ea" name="RBBM_PERFCTR_LRZ" stride="2" length="4" variants="A6XX"/> <array offset="0x04f2" name="RBBM_PERFCTR_CMP" stride="2" length="4" variants="A6XX"/> - <array offset="0x0300" name="RBBM_PERFCTR_CP" stride="2" length="14" variants="A7XX-"/> - <array offset="0x031c" name="RBBM_PERFCTR_RBBM" stride="2" length="4" variants="A7XX-"/> - <array offset="0x0324" name="RBBM_PERFCTR_PC" stride="2" length="8" variants="A7XX-"/> - <array offset="0x0334" name="RBBM_PERFCTR_VFD" stride="2" length="8" variants="A7XX-"/> - <array offset="0x0344" name="RBBM_PERFCTR_HLSQ" stride="2" length="6" variants="A7XX-"/> - <array offset="0x0350" name="RBBM_PERFCTR_VPC" stride="2" length="6" variants="A7XX-"/> - <array offset="0x035c" name="RBBM_PERFCTR_CCU" stride="2" length="5" variants="A7XX-"/> - <array offset="0x0366" name="RBBM_PERFCTR_TSE" stride="2" length="4" variants="A7XX-"/> - <array offset="0x036e" name="RBBM_PERFCTR_RAS" stride="2" length="4" variants="A7XX-"/> - <array offset="0x0376" name="RBBM_PERFCTR_UCHE" stride="2" length="12" variants="A7XX-"/> - <array offset="0x038e" name="RBBM_PERFCTR_TP" stride="2" length="12" variants="A7XX-"/> - <array offset="0x03a6" name="RBBM_PERFCTR_SP" stride="2" length="24" variants="A7XX-"/> - <array offset="0x03d6" name="RBBM_PERFCTR_RB" stride="2" length="8" variants="A7XX-"/> - <array offset="0x03e6" name="RBBM_PERFCTR_VSC" stride="2" length="2" variants="A7XX-"/> - <array offset="0x03ea" name="RBBM_PERFCTR_LRZ" stride="2" length="4" variants="A7XX-"/> - <array offset="0x03f2" name="RBBM_PERFCTR_CMP" stride="2" length="4" variants="A7XX-"/> - <array offset="0x03fa" name="RBBM_PERFCTR_UFC" stride="2" length="4" variants="A7XX-"/> - <array offset="0x0410" name="RBBM_PERFCTR2_HLSQ" stride="2" length="6" variants="A7XX-"/> - <array offset="0x041c" name="RBBM_PERFCTR2_CP" stride="2" length="7" variants="A7XX-"/> - <array offset="0x042a" name="RBBM_PERFCTR2_SP" stride="2" length="12" variants="A7XX-"/> - <array offset="0x0442" name="RBBM_PERFCTR2_TP" stride="2" length="6" variants="A7XX-"/> - <array offset="0x044e" name="RBBM_PERFCTR2_UFC" stride="2" length="2" variants="A7XX-"/> - <array offset="0x0460" name="RBBM_PERFCTR_BV_PC" stride="2" length="8" variants="A7XX-"/> - <array offset="0x0470" name="RBBM_PERFCTR_BV_VFD" stride="2" length="8" variants="A7XX-"/> - <array offset="0x0480" name="RBBM_PERFCTR_BV_VPC" stride="2" length="6" variants="A7XX-"/> - <array offset="0x048c" name="RBBM_PERFCTR_BV_TSE" stride="2" length="4" variants="A7XX-"/> - <array offset="0x0494" name="RBBM_PERFCTR_BV_RAS" stride="2" length="4" variants="A7XX-"/> - <array offset="0x049c" name="RBBM_PERFCTR_BV_LRZ" stride="2" length="4" variants="A7XX-"/> - - <reg32 offset="0x0500" name="RBBM_PERFCTR_CNTL"/> - <reg32 offset="0x0501" name="RBBM_PERFCTR_LOAD_CMD0"/> - <reg32 offset="0x0502" name="RBBM_PERFCTR_LOAD_CMD1"/> - <reg32 offset="0x0503" name="RBBM_PERFCTR_LOAD_CMD2"/> - <reg32 offset="0x0504" name="RBBM_PERFCTR_LOAD_CMD3"/> - <reg32 offset="0x0505" name="RBBM_PERFCTR_LOAD_VALUE_LO"/> - <reg32 offset="0x0506" name="RBBM_PERFCTR_LOAD_VALUE_HI"/> - <array offset="0x0507" name="RBBM_PERFCTR_RBBM_SEL" stride="1" length="4"/> - <reg32 offset="0x050B" name="RBBM_PERFCTR_GPU_BUSY_MASKED"/> - <reg32 offset="0x050e" name="RBBM_PERFCTR_SRAM_INIT_CMD"/> - <reg32 offset="0x050f" name="RBBM_PERFCTR_SRAM_INIT_STATUS"/> - <reg32 offset="0x0533" name="RBBM_ISDB_CNT"/> - <reg32 offset="0x0534" name="RBBM_NC_MODE_CNTL"/> - <reg32 offset="0x0535" name="RBBM_SNAPSHOT_STATUS" variants="A7XX-"/> + <array offset="0x0300" name="RBBM_PERFCTR_CP" stride="2" length="14" variants="A7XX"/> + <array offset="0x031c" name="RBBM_PERFCTR_RBBM" stride="2" length="4" variants="A7XX"/> + <array offset="0x0324" name="RBBM_PERFCTR_PC" stride="2" length="8" variants="A7XX"/> + <array offset="0x0334" name="RBBM_PERFCTR_VFD" stride="2" length="8" variants="A7XX"/> + <array offset="0x0344" name="RBBM_PERFCTR_HLSQ" stride="2" length="6" variants="A7XX"/> + <array offset="0x0350" name="RBBM_PERFCTR_VPC" stride="2" length="6" variants="A7XX"/> + <array offset="0x035c" name="RBBM_PERFCTR_CCU" stride="2" length="5" variants="A7XX"/> + <array offset="0x0366" name="RBBM_PERFCTR_TSE" stride="2" length="4" variants="A7XX"/> + <array offset="0x036e" name="RBBM_PERFCTR_RAS" stride="2" length="4" variants="A7XX"/> + <array offset="0x0376" name="RBBM_PERFCTR_UCHE" stride="2" length="12" variants="A7XX"/> + <array offset="0x038e" name="RBBM_PERFCTR_TP" stride="2" length="12" variants="A7XX"/> + <array offset="0x03a6" name="RBBM_PERFCTR_SP" stride="2" length="24" variants="A7XX"/> + <array offset="0x03d6" name="RBBM_PERFCTR_RB" stride="2" length="8" variants="A7XX"/> + <array offset="0x03e6" name="RBBM_PERFCTR_VSC" stride="2" length="2" variants="A7XX"/> + <array offset="0x03ea" name="RBBM_PERFCTR_LRZ" stride="2" length="4" variants="A7XX"/> + <array offset="0x03f2" name="RBBM_PERFCTR_CMP" stride="2" length="4" variants="A7XX"/> + <array offset="0x03fa" name="RBBM_PERFCTR_UFC" stride="2" length="4" variants="A7XX"/> + <array offset="0x0410" name="RBBM_PERFCTR2_HLSQ" stride="2" length="6" variants="A7XX"/> + <array offset="0x041c" name="RBBM_PERFCTR2_CP" stride="2" length="7" variants="A7XX"/> + <array offset="0x042a" name="RBBM_PERFCTR2_SP" stride="2" length="12" variants="A7XX"/> + <array offset="0x0442" name="RBBM_PERFCTR2_TP" stride="2" length="6" variants="A7XX"/> + <array offset="0x044e" name="RBBM_PERFCTR2_UFC" stride="2" length="2" variants="A7XX"/> + <array offset="0x0460" name="RBBM_PERFCTR_BV_PC" stride="2" length="8" variants="A7XX"/> + <array offset="0x0470" name="RBBM_PERFCTR_BV_VFD" stride="2" length="8" variants="A7XX"/> + <array offset="0x0480" name="RBBM_PERFCTR_BV_VPC" stride="2" length="6" variants="A7XX"/> + <array offset="0x048c" name="RBBM_PERFCTR_BV_TSE" stride="2" length="4" variants="A7XX"/> + <array offset="0x0494" name="RBBM_PERFCTR_BV_RAS" stride="2" length="4" variants="A7XX"/> + <array offset="0x049c" name="RBBM_PERFCTR_BV_LRZ" stride="2" length="4" variants="A7XX"/> + + <array offset="0x01b0" name="RBBM_PERFCTR_CP" stride="2" length="14" variants="A8XX"/> + <array offset="0x01cc" name="RBBM_PERFCTR_RBBM" stride="2" length="4" variants="A8XX"/> + <array offset="0x01d4" name="RBBM_PERFCTR_PC" stride="2" length="8" variants="A8XX"/> + <array offset="0x01e4" name="RBBM_PERFCTR_VFD" stride="2" length="8" variants="A8XX"/> + <array offset="0x01f4" name="RBBM_PERFCTR_HLSQ" stride="2" length="6" variants="A8XX"/> + <array offset="0x0200" name="RBBM_PERFCTR_VPC" stride="2" length="6" variants="A8XX"/> + <array offset="0x020c" name="RBBM_PERFCTR_CCU" stride="2" length="5" variants="A8XX"/> + <array offset="0x0216" name="RBBM_PERFCTR_TSE" stride="2" length="4" variants="A8XX"/> + <array offset="0x021e" name="RBBM_PERFCTR_RAS" stride="2" length="4" variants="A8XX"/> + <array offset="0x0226" name="RBBM_PERFCTR_UCHE" stride="2" length="24" variants="A8XX"/> + <array offset="0x0256" name="RBBM_PERFCTR_TP" stride="2" length="12" variants="A8XX"/> + <array offset="0x026e" name="RBBM_PERFCTR_SP" stride="2" length="24" variants="A8XX"/> + <array offset="0x029e" name="RBBM_PERFCTR_RB" stride="2" length="8" variants="A8XX"/> + <array offset="0x02ae" name="RBBM_PERFCTR_VSC" stride="2" length="2" variants="A8XX"/> + <array offset="0x02b2" name="RBBM_PERFCTR_LRZ" stride="2" length="4" variants="A8XX"/> + <array offset="0x02ba" name="RBBM_PERFCTR_CMP" stride="2" length="4" variants="A8XX"/> + <array offset="0x02c2" name="RBBM_PERFCTR_UFC" stride="2" length="4" variants="A8XX"/> + <array offset="0x02e2" name="RBBM_PERFCTR2_HLSQ" stride="2" length="6" variants="A8XX"/> + <array offset="0x02ee" name="RBBM_PERFCTR2_CP" stride="2" length="7" variants="A8XX"/> + <array offset="0x02fc" name="RBBM_PERFCTR2_SP" stride="2" length="12" variants="A8XX"/> + <array offset="0x0314" name="RBBM_PERFCTR2_TP" stride="2" length="8" variants="A8XX"/> + <array offset="0x0324" name="RBBM_PERFCTR2_UFC" stride="2" length="2" variants="A8XX"/> + <array offset="0x0328" name="RBBM_PERFCTR_BV_PC" stride="2" length="8" variants="A8XX"/> + <array offset="0x0338" name="RBBM_PERFCTR_BV_VFD" stride="2" length="8" variants="A8XX"/> + <array offset="0x0348" name="RBBM_PERFCTR_BV_VPC" stride="2" length="6" variants="A8XX"/> + <array offset="0x0354" name="RBBM_PERFCTR_BV_TSE" stride="2" length="4" variants="A8XX"/> + <array offset="0x035c" name="RBBM_PERFCTR_BV_RAS" stride="2" length="4" variants="A8XX"/> + <array offset="0x0364" name="RBBM_PERFCTR_BV_LRZ" stride="2" length="4" variants="A8XX"/> + <array offset="0x036c" name="RBBM_PERFCTR_BV_CCU" stride="2" length="3" variants="A8XX"/> + <array offset="0x0372" name="RBBM_PERFCTR_BV_RB" stride="2" length="6" variants="A8XX"/> + + <reg32 offset="0x0500" name="RBBM_PERFCTR_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x0460" name="RBBM_PERFCTR_CNTL" variants="A8XX-"/> + <reg32 offset="0x0501" name="RBBM_PERFCTR_LOAD_CMD0" variants="A6XX"/> + <reg32 offset="0x0502" name="RBBM_PERFCTR_LOAD_CMD1" variants="A6XX"/> + <reg32 offset="0x0503" name="RBBM_PERFCTR_LOAD_CMD2" variants="A6XX"/> + <reg32 offset="0x0504" name="RBBM_PERFCTR_LOAD_CMD3" variants="A6XX"/> + <reg64 offset="0x0505" name="RBBM_PERFCTR_LOAD_VALUE" variants="A6XX"/> + <array offset="0x0507" name="RBBM_PERFCTR_RBBM_SEL" stride="1" length="4" variants="A6XX-A7XX"/> + <array offset="0x0441" name="RBBM_PERFCTR_RBBM_SEL" stride="1" length="4" variants="A8XX-"/> + <reg32 offset="0x050B" name="RBBM_PERFCTR_GPU_BUSY_MASKED" variants="A6XX-A7XX"/> + <reg32 offset="0x019e" name="RBBM_PERFCTR_GPU_BUSY_MASKED" variants="A8XX-"/> + <reg32 offset="0x050e" name="RBBM_PERFCTR_SRAM_INIT_CMD" variants="A6XX-A7XX"/> + <reg32 offset="0x0449" name="RBBM_PERFCTR_SRAM_INIT_CMD" variants="A8XX-"/> + <reg32 offset="0x050f" name="RBBM_PERFCTR_SRAM_INIT_STATUS" variants="A6XX-A7XX"/> + <reg32 offset="0x019f" name="RBBM_PERFCTR_SRAM_INIT_STATUS" variants="A8XX-"/> + <reg32 offset="0x01a1" name="RBBM_PERFCTR_FLUSH_HOST_STATUS" variants="A8XX-"/> + <reg32 offset="0x044c" name="RBBM_PERFCTR_FLUSH_HOST_CMD" variants="A8XX-"/> + <reg32 offset="0x0533" name="RBBM_ISDB_CNT" variants="A6XX-A7XX"/> + <reg32 offset="0x002d" name="RBBM_ISDB_CNT" variants="A8XX-"/> + <reg32 offset="0x0534" name="RBBM_NC_MODE_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x0440" name="RBBM_NC_MODE_CNTL" variants="A8XX-"/> + <reg32 offset="0x0535" name="RBBM_SNAPSHOT_STATUS" variants="A7XX"/> + <reg32 offset="0x002e" name="RBBM_SNAPSHOT_STATUS" variants="A8XX-"/> + + <reg32 offset="0x500" name="RBBM_SLICE_PERFCTR_CNTL" variants="A8XX-"/> + <reg32 offset="0x58f" name="RBBM_SLICE_INTERFACE_HANG_INT_CNTL" variants="A8XX-"/> + <array offset="0x5e0" name="RBBM_SLICE_PERFCTR_RBBM_SEL" stride="1" length="4" variants="A8XX-"/> + <reg32 offset="0x5e8" name="RBBM_SLICE_PERFCTR_SRAM_INIT_CMD" variants="A8XX-"/> + <reg32 offset="0x5eb" name="RBBM_SLICE_PERFCTR_FLUSH_HOST_CMD" variants="A8XX-"/> + <reg32 offset="0x5ec" name="RBBM_SLICE_NC_MODE_CNTL" variants="A8XX-"/> <!--- This block of registers aren't tied to perf counters. They @@ -2619,189 +739,223 @@ to upconvert to 32b float internally? vertices in, number of primnitives assembled etc. --> - <reg32 offset="0x0540" name="RBBM_PRIMCTR_0_LO"/> <!-- vs vertices in --> - <reg32 offset="0x0541" name="RBBM_PRIMCTR_0_HI"/> - <reg32 offset="0x0542" name="RBBM_PRIMCTR_1_LO"/> <!-- vs primitives out --> - <reg32 offset="0x0543" name="RBBM_PRIMCTR_1_HI"/> - <reg32 offset="0x0544" name="RBBM_PRIMCTR_2_LO"/> <!-- hs vertices in --> - <reg32 offset="0x0545" name="RBBM_PRIMCTR_2_HI"/> - <reg32 offset="0x0546" name="RBBM_PRIMCTR_3_LO"/> <!-- hs patches out --> - <reg32 offset="0x0547" name="RBBM_PRIMCTR_3_HI"/> - <reg32 offset="0x0548" name="RBBM_PRIMCTR_4_LO"/> <!-- dss vertices in --> - <reg32 offset="0x0549" name="RBBM_PRIMCTR_4_HI"/> - <reg32 offset="0x054a" name="RBBM_PRIMCTR_5_LO"/> <!-- ds primitives out --> - <reg32 offset="0x054b" name="RBBM_PRIMCTR_5_HI"/> - <reg32 offset="0x054c" name="RBBM_PRIMCTR_6_LO"/> <!-- gs primitives in --> - <reg32 offset="0x054d" name="RBBM_PRIMCTR_6_HI"/> - <reg32 offset="0x054e" name="RBBM_PRIMCTR_7_LO"/> <!-- gs primitives out --> - <reg32 offset="0x054f" name="RBBM_PRIMCTR_7_HI"/> - <reg32 offset="0x0550" name="RBBM_PRIMCTR_8_LO"/> <!-- gs primitives out --> - <reg32 offset="0x0551" name="RBBM_PRIMCTR_8_HI"/> - <reg32 offset="0x0552" name="RBBM_PRIMCTR_9_LO"/> <!-- raster primitives in --> - <reg32 offset="0x0553" name="RBBM_PRIMCTR_9_HI"/> - <reg32 offset="0x0554" name="RBBM_PRIMCTR_10_LO"/> - <reg32 offset="0x0555" name="RBBM_PRIMCTR_10_HI"/> + <reg64 offset="0x0540" name="RBBM_PIPESTAT_IAVERTICES" variants="A6XX-A7XX"/> + <reg64 offset="0x0542" name="RBBM_PIPESTAT_IAPRIMITIVES" variants="A6XX-A7XX"/> + <reg64 offset="0x0544" name="RBBM_PIPESTAT_VSINVOCATIONS" variants="A6XX-A7XX"/> + <reg64 offset="0x0546" name="RBBM_PIPESTAT_HSINVOCATIONS" variants="A6XX-A7XX"/> + <reg64 offset="0x0548" name="RBBM_PIPESTAT_DSINVOCATIONS" variants="A6XX-A7XX"/> + <reg64 offset="0x054a" name="RBBM_PIPESTAT_GSINVOCATIONS" variants="A6XX-A7XX"/> + <reg64 offset="0x054c" name="RBBM_PIPESTAT_GSPRIMITIVES" variants="A6XX-A7XX"/> + <reg64 offset="0x054e" name="RBBM_PIPESTAT_CINVOCATIONS" variants="A6XX-A7XX"/> + <reg64 offset="0x0550" name="RBBM_PIPESTAT_CPRIMITIVES" variants="A6XX-A7XX"/> + <reg64 offset="0x0552" name="RBBM_PIPESTAT_PSINVOCATIONS" variants="A6XX-A7XX"/> + <reg64 offset="0x0554" name="RBBM_PIPESTAT_CSINVOCATIONS" variants="A6XX-A7XX"/> + + <reg64 offset="0x0380" name="RBBM_PIPESTAT_IAVERTICES" variants="A8XX-"/> + <reg64 offset="0x0382" name="RBBM_PIPESTAT_IAPRIMITIVES" variants="A8XX-"/> + <reg64 offset="0x0384" name="RBBM_PIPESTAT_VSINVOCATIONS" variants="A8XX-"/> + <reg64 offset="0x0386" name="RBBM_PIPESTAT_GSINVOCATIONS" variants="A8XX-"/> + <reg64 offset="0x0388" name="RBBM_PIPESTAT_GSPRIMITIVES" variants="A8XX-"/> + <reg64 offset="0x038a" name="RBBM_PIPESTAT_CINVOCATIONS" variants="A8XX-"/> + <reg64 offset="0x038c" name="RBBM_PIPESTAT_CPRIMITIVES" variants="A8XX-"/> + <reg64 offset="0x038e" name="RBBM_PIPESTAT_PSINVOCATIONS" variants="A8XX-"/> + <reg64 offset="0x0390" name="RBBM_PIPESTAT_HSINVOCATIONS" variants="A8XX-"/> + <reg64 offset="0x0392" name="RBBM_PIPESTAT_DSINVOCATIONS" variants="A8XX-"/> + <reg64 offset="0x0394" name="RBBM_PIPESTAT_CSINVOCATIONS" variants="A8XX-"/> + <reg64 offset="0x0396" name="RBBM_PIPESTAT_ASINVOCATIONS" variants="A8XX-"/> + <reg64 offset="0x0398" name="RBBM_PIPESTAT_MSINVOCATIONS" variants="A8XX-"/> + <reg64 offset="0x039a" name="RBBM_PIPESTAT_MSPRIMITIVES" variants="A8XX-"/> <reg32 offset="0xF400" name="RBBM_SECVID_TRUST_CNTL"/> <reg64 offset="0xF800" name="RBBM_SECVID_TSB_TRUSTED_BASE"/> <reg32 offset="0xF802" name="RBBM_SECVID_TSB_TRUSTED_SIZE"/> <reg32 offset="0xF803" name="RBBM_SECVID_TSB_CNTL"/> - <reg32 offset="0xF810" name="RBBM_SECVID_TSB_ADDR_MODE_CNTL" type="a5xx_address_mode"/> + <reg32 offset="0xF810" name="RBBM_SECVID_TSB_ADDR_MODE_CNTL" type="a5xx_address_mode" variants="A6XX"/> <reg64 offset="0xfc00" name="RBBM_SECVID_TSB_STATUS" variants="A7XX-"/> - <reg32 offset="0x00010" name="RBBM_VBIF_CLIENT_QOS_CNTL"/> - <reg32 offset="0x00011" name="RBBM_GBIF_CLIENT_QOS_CNTL"/> - <reg32 offset="0x00016" name="RBBM_GBIF_HALT"/> - <reg32 offset="0x00017" name="RBBM_GBIF_HALT_ACK"/> - <reg32 offset="0x0001c" name="RBBM_WAIT_FOR_GPU_IDLE_CMD"> + <reg32 offset="0x00010" name="RBBM_VBIF_CLIENT_QOS_CNTL" variants="A6XX"/> + <reg32 offset="0x00011" name="RBBM_GBIF_CLIENT_QOS_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x00008" name="RBBM_GBIF_CLIENT_QOS_CNTL" variants="A8XX-"/> + <reg32 offset="0x00016" name="RBBM_GBIF_HALT" variants="A6XX-A7XX"/> + <reg32 offset="0x0000a" name="RBBM_GBIF_HALT" variants="A8XX-"/> + <reg32 offset="0x00017" name="RBBM_GBIF_HALT_ACK" variants="A6XX-A7XX"/> + <reg32 offset="0x0000b" name="RBBM_GBIF_HALT_ACK" variants="A8XX-"/> + <reg32 offset="0x0001c" name="RBBM_WAIT_FOR_GPU_IDLE_CMD" variants="A6XX"> <bitfield pos="0" name="WAIT_GPU_IDLE" type="boolean"/> </reg32> - <reg32 offset="0x00016" name="RBBM_GBIF_HALT" variants="A7XX-"/> - <reg32 offset="0x00017" name="RBBM_GBIF_HALT_ACK" variants="A7XX-"/> - <reg32 offset="0x0001f" name="RBBM_INTERFACE_HANG_INT_CNTL"/> - <reg32 offset="0x00037" name="RBBM_INT_CLEAR_CMD" type="A6XX_RBBM_INT_0_MASK"/> - <reg32 offset="0x00038" name="RBBM_INT_0_MASK" type="A6XX_RBBM_INT_0_MASK"/> - <reg32 offset="0x0003a" name="RBBM_INT_2_MASK" variants="A7XX-"/> - <reg32 offset="0x00042" name="RBBM_SP_HYST_CNT"/> - <reg32 offset="0x00043" name="RBBM_SW_RESET_CMD"/> - <reg32 offset="0x00044" name="RBBM_RAC_THRESHOLD_CNT"/> - <reg32 offset="0x00045" name="RBBM_BLOCK_SW_RESET_CMD"/> - <reg32 offset="0x00046" name="RBBM_BLOCK_SW_RESET_CMD2"/> - <reg32 offset="0x000ad" name="RBBM_CLOCK_CNTL_GLOBAL" variants="A7XX-"/> - <reg32 offset="0x000ae" name="RBBM_CLOCK_CNTL"/> - <reg32 offset="0x000b0" name="RBBM_CLOCK_CNTL_SP0"/> - <reg32 offset="0x000b1" name="RBBM_CLOCK_CNTL_SP1"/> - <reg32 offset="0x000b2" name="RBBM_CLOCK_CNTL_SP2"/> - <reg32 offset="0x000b3" name="RBBM_CLOCK_CNTL_SP3"/> - <reg32 offset="0x000b4" name="RBBM_CLOCK_CNTL2_SP0"/> - <reg32 offset="0x000b5" name="RBBM_CLOCK_CNTL2_SP1"/> - <reg32 offset="0x000b6" name="RBBM_CLOCK_CNTL2_SP2"/> - <reg32 offset="0x000b7" name="RBBM_CLOCK_CNTL2_SP3"/> - <reg32 offset="0x000b8" name="RBBM_CLOCK_DELAY_SP0"/> - <reg32 offset="0x000b9" name="RBBM_CLOCK_DELAY_SP1"/> - <reg32 offset="0x000ba" name="RBBM_CLOCK_DELAY_SP2"/> - <reg32 offset="0x000bb" name="RBBM_CLOCK_DELAY_SP3"/> - <reg32 offset="0x000bc" name="RBBM_CLOCK_HYST_SP0"/> - <reg32 offset="0x000bd" name="RBBM_CLOCK_HYST_SP1"/> - <reg32 offset="0x000be" name="RBBM_CLOCK_HYST_SP2"/> - <reg32 offset="0x000bf" name="RBBM_CLOCK_HYST_SP3"/> - <reg32 offset="0x000c0" name="RBBM_CLOCK_CNTL_TP0"/> - <reg32 offset="0x000c1" name="RBBM_CLOCK_CNTL_TP1"/> - <reg32 offset="0x000c2" name="RBBM_CLOCK_CNTL_TP2"/> - <reg32 offset="0x000c3" name="RBBM_CLOCK_CNTL_TP3"/> - <reg32 offset="0x000c4" name="RBBM_CLOCK_CNTL2_TP0"/> - <reg32 offset="0x000c5" name="RBBM_CLOCK_CNTL2_TP1"/> - <reg32 offset="0x000c6" name="RBBM_CLOCK_CNTL2_TP2"/> - <reg32 offset="0x000c7" name="RBBM_CLOCK_CNTL2_TP3"/> - <reg32 offset="0x000c8" name="RBBM_CLOCK_CNTL3_TP0"/> - <reg32 offset="0x000c9" name="RBBM_CLOCK_CNTL3_TP1"/> - <reg32 offset="0x000ca" name="RBBM_CLOCK_CNTL3_TP2"/> - <reg32 offset="0x000cb" name="RBBM_CLOCK_CNTL3_TP3"/> - <reg32 offset="0x000cc" name="RBBM_CLOCK_CNTL4_TP0"/> - <reg32 offset="0x000cd" name="RBBM_CLOCK_CNTL4_TP1"/> - <reg32 offset="0x000ce" name="RBBM_CLOCK_CNTL4_TP2"/> - <reg32 offset="0x000cf" name="RBBM_CLOCK_CNTL4_TP3"/> - <reg32 offset="0x000d0" name="RBBM_CLOCK_DELAY_TP0"/> - <reg32 offset="0x000d1" name="RBBM_CLOCK_DELAY_TP1"/> - <reg32 offset="0x000d2" name="RBBM_CLOCK_DELAY_TP2"/> - <reg32 offset="0x000d3" name="RBBM_CLOCK_DELAY_TP3"/> - <reg32 offset="0x000d4" name="RBBM_CLOCK_DELAY2_TP0"/> - <reg32 offset="0x000d5" name="RBBM_CLOCK_DELAY2_TP1"/> - <reg32 offset="0x000d6" name="RBBM_CLOCK_DELAY2_TP2"/> - <reg32 offset="0x000d7" name="RBBM_CLOCK_DELAY2_TP3"/> - <reg32 offset="0x000d8" name="RBBM_CLOCK_DELAY3_TP0"/> - <reg32 offset="0x000d9" name="RBBM_CLOCK_DELAY3_TP1"/> - <reg32 offset="0x000da" name="RBBM_CLOCK_DELAY3_TP2"/> - <reg32 offset="0x000db" name="RBBM_CLOCK_DELAY3_TP3"/> - <reg32 offset="0x000dc" name="RBBM_CLOCK_DELAY4_TP0"/> - <reg32 offset="0x000dd" name="RBBM_CLOCK_DELAY4_TP1"/> - <reg32 offset="0x000de" name="RBBM_CLOCK_DELAY4_TP2"/> - <reg32 offset="0x000df" name="RBBM_CLOCK_DELAY4_TP3"/> - <reg32 offset="0x000e0" name="RBBM_CLOCK_HYST_TP0"/> - <reg32 offset="0x000e1" name="RBBM_CLOCK_HYST_TP1"/> - <reg32 offset="0x000e2" name="RBBM_CLOCK_HYST_TP2"/> - <reg32 offset="0x000e3" name="RBBM_CLOCK_HYST_TP3"/> - <reg32 offset="0x000e4" name="RBBM_CLOCK_HYST2_TP0"/> - <reg32 offset="0x000e5" name="RBBM_CLOCK_HYST2_TP1"/> - <reg32 offset="0x000e6" name="RBBM_CLOCK_HYST2_TP2"/> - <reg32 offset="0x000e7" name="RBBM_CLOCK_HYST2_TP3"/> - <reg32 offset="0x000e8" name="RBBM_CLOCK_HYST3_TP0"/> - <reg32 offset="0x000e9" name="RBBM_CLOCK_HYST3_TP1"/> - <reg32 offset="0x000ea" name="RBBM_CLOCK_HYST3_TP2"/> - <reg32 offset="0x000eb" name="RBBM_CLOCK_HYST3_TP3"/> - <reg32 offset="0x000ec" name="RBBM_CLOCK_HYST4_TP0"/> - <reg32 offset="0x000ed" name="RBBM_CLOCK_HYST4_TP1"/> - <reg32 offset="0x000ee" name="RBBM_CLOCK_HYST4_TP2"/> - <reg32 offset="0x000ef" name="RBBM_CLOCK_HYST4_TP3"/> - <reg32 offset="0x000f0" name="RBBM_CLOCK_CNTL_RB0"/> - <reg32 offset="0x000f1" name="RBBM_CLOCK_CNTL_RB1"/> - <reg32 offset="0x000f2" name="RBBM_CLOCK_CNTL_RB2"/> - <reg32 offset="0x000f3" name="RBBM_CLOCK_CNTL_RB3"/> - <reg32 offset="0x000f4" name="RBBM_CLOCK_CNTL2_RB0"/> - <reg32 offset="0x000f5" name="RBBM_CLOCK_CNTL2_RB1"/> - <reg32 offset="0x000f6" name="RBBM_CLOCK_CNTL2_RB2"/> - <reg32 offset="0x000f7" name="RBBM_CLOCK_CNTL2_RB3"/> - <reg32 offset="0x000f8" name="RBBM_CLOCK_CNTL_CCU0"/> - <reg32 offset="0x000f9" name="RBBM_CLOCK_CNTL_CCU1"/> - <reg32 offset="0x000fa" name="RBBM_CLOCK_CNTL_CCU2"/> - <reg32 offset="0x000fb" name="RBBM_CLOCK_CNTL_CCU3"/> - <reg32 offset="0x00100" name="RBBM_CLOCK_HYST_RB_CCU0"/> - <reg32 offset="0x00101" name="RBBM_CLOCK_HYST_RB_CCU1"/> - <reg32 offset="0x00102" name="RBBM_CLOCK_HYST_RB_CCU2"/> - <reg32 offset="0x00103" name="RBBM_CLOCK_HYST_RB_CCU3"/> - <reg32 offset="0x00104" name="RBBM_CLOCK_CNTL_RAC"/> - <reg32 offset="0x00105" name="RBBM_CLOCK_CNTL2_RAC"/> - <reg32 offset="0x00106" name="RBBM_CLOCK_DELAY_RAC"/> - <reg32 offset="0x00107" name="RBBM_CLOCK_HYST_RAC"/> - <reg32 offset="0x00108" name="RBBM_CLOCK_CNTL_TSE_RAS_RBBM"/> - <reg32 offset="0x00109" name="RBBM_CLOCK_DELAY_TSE_RAS_RBBM"/> - <reg32 offset="0x0010a" name="RBBM_CLOCK_HYST_TSE_RAS_RBBM"/> - <reg32 offset="0x0010b" name="RBBM_CLOCK_CNTL_UCHE"/> - <reg32 offset="0x0010c" name="RBBM_CLOCK_CNTL2_UCHE"/> - <reg32 offset="0x0010d" name="RBBM_CLOCK_CNTL3_UCHE"/> - <reg32 offset="0x0010e" name="RBBM_CLOCK_CNTL4_UCHE"/> - <reg32 offset="0x0010f" name="RBBM_CLOCK_DELAY_UCHE"/> - <reg32 offset="0x00110" name="RBBM_CLOCK_HYST_UCHE"/> - <reg32 offset="0x00111" name="RBBM_CLOCK_MODE_VFD"/> - <reg32 offset="0x00112" name="RBBM_CLOCK_DELAY_VFD"/> - <reg32 offset="0x00113" name="RBBM_CLOCK_HYST_VFD"/> - <reg32 offset="0x00114" name="RBBM_CLOCK_MODE_GPC"/> - <reg32 offset="0x00115" name="RBBM_CLOCK_DELAY_GPC"/> - <reg32 offset="0x00116" name="RBBM_CLOCK_HYST_GPC"/> - <reg32 offset="0x00117" name="RBBM_CLOCK_DELAY_HLSQ_2"/> - <reg32 offset="0x00118" name="RBBM_CLOCK_CNTL_GMU_GX"/> - <reg32 offset="0x00119" name="RBBM_CLOCK_DELAY_GMU_GX"/> - <reg32 offset="0x0011a" name="RBBM_CLOCK_HYST_GMU_GX"/> - <reg32 offset="0x0011b" name="RBBM_CLOCK_MODE_HLSQ"/> - <reg32 offset="0x0011c" name="RBBM_CLOCK_DELAY_HLSQ"/> - <reg32 offset="0x0011d" name="RBBM_CLOCK_HYST_HLSQ"/> - <reg32 offset="0x0011e" name="RBBM_CGC_GLOBAL_LOAD_CMD" variants="A7XX-"/> - <reg32 offset="0x0011f" name="RBBM_CGC_P2S_TRIG_CMD" variants="A7XX-"/> - <reg32 offset="0x00120" name="RBBM_CLOCK_CNTL_TEX_FCHE"/> - <reg32 offset="0x00121" name="RBBM_CLOCK_DELAY_TEX_FCHE"/> - <reg32 offset="0x00122" name="RBBM_CLOCK_HYST_TEX_FCHE"/> - <reg32 offset="0x00122" name="RBBM_CGC_P2S_STATUS" variants="A7XX-"> + <reg32 offset="0x01a" name="RBBM_WAIT_IDLE_CLOCKS_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x01b" name="RBBM_WAIT_IDLE_CLOCKS_CNTL2" variants="A6XX-A7XX"/> + <reg32 offset="0x010" name="RBBM_WAIT_IDLE_CLOCKS_CNTL" variants="A8XX-"/> + <reg32 offset="0x011" name="RBBM_WAIT_IDLE_CLOCKS_CNTL2" variants="A8XX-"/> + + <reg32 offset="0x0001f" name="RBBM_INTERFACE_HANG_INT_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x0002f" name="RBBM_INTERFACE_HANG_INT_CNTL" variants="A8XX-"/> + <reg32 offset="0x00037" name="RBBM_INT_CLEAR_CMD" type="A6XX_RBBM_INT_0_MASK" variants="A6XX-A7XX"/> + <reg32 offset="0x00061" name="RBBM_INT_CLEAR_CMD" type="A6XX_RBBM_INT_0_MASK" variants="A8XX-"/> + <reg32 offset="0x00038" name="RBBM_INT_0_MASK" type="A6XX_RBBM_INT_0_MASK" variants="A6XX-A7XX"/> + <reg32 offset="0x00062" name="RBBM_INT_0_MASK" type="A6XX_RBBM_INT_0_MASK" variants="A8XX-"/> + <reg32 offset="0x0003a" name="RBBM_INT_2_MASK" variants="A7XX"/> + <reg32 offset="0x00064" name="RBBM_INT_2_MASK" variants="A8XX-"/> + <reg32 offset="0x00042" name="RBBM_SP_HYST_CNT" variants="A6XX-A7XX"/> + <reg32 offset="0x00043" name="RBBM_SW_RESET_CMD" variants="A6XX-A7XX"/> + <reg32 offset="0x00073" name="RBBM_SW_RESET_CMD" variants="A8XX-"/> + <reg32 offset="0x00044" name="RBBM_RAC_THRESHOLD_CNT" variants="A6XX-A7XX"/> + <reg32 offset="0x00029" name="RBBM_RAC_THRESHOLD_CNT" variants="A8XX-"/> + <reg32 offset="0x00045" name="RBBM_BLOCK_SW_RESET_CMD" variants="A6XX"/> + <reg32 offset="0x00046" name="RBBM_BLOCK_SW_RESET_CMD2" variants="A6XX"/> + <reg32 offset="0x000ad" name="RBBM_CLOCK_CNTL_GLOBAL" variants="A7XX"/> + <reg32 offset="0x0009a" name="RBBM_CLOCK_CNTL_GLOBAL" variants="A8XX-"/> + <reg32 offset="0x07d" name="RBBM_POWER_UP_RESET_SW_OVERRIDE" variants="A8XX-"/> + <reg32 offset="0x07e" name="RBBM_POWER_UP_RESET_SW_BV_OVERRIDE" variants="A8XX-"/> + <reg32 offset="0x000ae" name="RBBM_CLOCK_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x000b0" name="RBBM_CLOCK_CNTL_SP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000b1" name="RBBM_CLOCK_CNTL_SP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000b2" name="RBBM_CLOCK_CNTL_SP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000b3" name="RBBM_CLOCK_CNTL_SP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000b4" name="RBBM_CLOCK_CNTL2_SP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000b5" name="RBBM_CLOCK_CNTL2_SP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000b6" name="RBBM_CLOCK_CNTL2_SP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000b7" name="RBBM_CLOCK_CNTL2_SP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000b8" name="RBBM_CLOCK_DELAY_SP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000b9" name="RBBM_CLOCK_DELAY_SP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000ba" name="RBBM_CLOCK_DELAY_SP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000bb" name="RBBM_CLOCK_DELAY_SP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000bc" name="RBBM_CLOCK_HYST_SP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000bd" name="RBBM_CLOCK_HYST_SP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000be" name="RBBM_CLOCK_HYST_SP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000bf" name="RBBM_CLOCK_HYST_SP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000c0" name="RBBM_CLOCK_CNTL_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000c1" name="RBBM_CLOCK_CNTL_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000c2" name="RBBM_CLOCK_CNTL_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000c3" name="RBBM_CLOCK_CNTL_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000c4" name="RBBM_CLOCK_CNTL2_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000c5" name="RBBM_CLOCK_CNTL2_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000c6" name="RBBM_CLOCK_CNTL2_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000c7" name="RBBM_CLOCK_CNTL2_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000c8" name="RBBM_CLOCK_CNTL3_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000c9" name="RBBM_CLOCK_CNTL3_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000ca" name="RBBM_CLOCK_CNTL3_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000cb" name="RBBM_CLOCK_CNTL3_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000cc" name="RBBM_CLOCK_CNTL4_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000cd" name="RBBM_CLOCK_CNTL4_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000ce" name="RBBM_CLOCK_CNTL4_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000cf" name="RBBM_CLOCK_CNTL4_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000d0" name="RBBM_CLOCK_DELAY_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000d1" name="RBBM_CLOCK_DELAY_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000d2" name="RBBM_CLOCK_DELAY_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000d3" name="RBBM_CLOCK_DELAY_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000d4" name="RBBM_CLOCK_DELAY2_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000d5" name="RBBM_CLOCK_DELAY2_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000d6" name="RBBM_CLOCK_DELAY2_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000d7" name="RBBM_CLOCK_DELAY2_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000d8" name="RBBM_CLOCK_DELAY3_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000d9" name="RBBM_CLOCK_DELAY3_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000da" name="RBBM_CLOCK_DELAY3_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000db" name="RBBM_CLOCK_DELAY3_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000dc" name="RBBM_CLOCK_DELAY4_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000dd" name="RBBM_CLOCK_DELAY4_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000de" name="RBBM_CLOCK_DELAY4_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000df" name="RBBM_CLOCK_DELAY4_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000e0" name="RBBM_CLOCK_HYST_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000e1" name="RBBM_CLOCK_HYST_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000e2" name="RBBM_CLOCK_HYST_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000e3" name="RBBM_CLOCK_HYST_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000e4" name="RBBM_CLOCK_HYST2_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000e5" name="RBBM_CLOCK_HYST2_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000e6" name="RBBM_CLOCK_HYST2_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000e7" name="RBBM_CLOCK_HYST2_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000e8" name="RBBM_CLOCK_HYST3_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000e9" name="RBBM_CLOCK_HYST3_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000ea" name="RBBM_CLOCK_HYST3_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000eb" name="RBBM_CLOCK_HYST3_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000ec" name="RBBM_CLOCK_HYST4_TP0" variants="A6XX-A7XX"/> + <reg32 offset="0x000ed" name="RBBM_CLOCK_HYST4_TP1" variants="A6XX-A7XX"/> + <reg32 offset="0x000ee" name="RBBM_CLOCK_HYST4_TP2" variants="A6XX-A7XX"/> + <reg32 offset="0x000ef" name="RBBM_CLOCK_HYST4_TP3" variants="A6XX-A7XX"/> + <reg32 offset="0x000f0" name="RBBM_CLOCK_CNTL_RB0" variants="A6XX-A7XX"/> + <reg32 offset="0x000f1" name="RBBM_CLOCK_CNTL_RB1" variants="A6XX-A7XX"/> + <reg32 offset="0x000f2" name="RBBM_CLOCK_CNTL_RB2" variants="A6XX-A7XX"/> + <reg32 offset="0x000f3" name="RBBM_CLOCK_CNTL_RB3" variants="A6XX-A7XX"/> + <reg32 offset="0x000f4" name="RBBM_CLOCK_CNTL2_RB0" variants="A6XX-A7XX"/> + <reg32 offset="0x000f5" name="RBBM_CLOCK_CNTL2_RB1" variants="A6XX-A7XX"/> + <reg32 offset="0x000f6" name="RBBM_CLOCK_CNTL2_RB2" variants="A6XX-A7XX"/> + <reg32 offset="0x000f7" name="RBBM_CLOCK_CNTL2_RB3" variants="A6XX-A7XX"/> + <reg32 offset="0x000f8" name="RBBM_CLOCK_CNTL_CCU0" variants="A6XX-A7XX"/> + <reg32 offset="0x000f9" name="RBBM_CLOCK_CNTL_CCU1" variants="A6XX-A7XX"/> + <reg32 offset="0x000fa" name="RBBM_CLOCK_CNTL_CCU2" variants="A6XX-A7XX"/> + <reg32 offset="0x000fb" name="RBBM_CLOCK_CNTL_CCU3" variants="A6XX-A7XX"/> + <reg32 offset="0x00100" name="RBBM_CLOCK_HYST_RB_CCU0" variants="A6XX-A7XX"/> + <reg32 offset="0x00101" name="RBBM_CLOCK_HYST_RB_CCU1" variants="A6XX-A7XX"/> + <reg32 offset="0x00102" name="RBBM_CLOCK_HYST_RB_CCU2" variants="A6XX-A7XX"/> + <reg32 offset="0x00103" name="RBBM_CLOCK_HYST_RB_CCU3" variants="A6XX-A7XX"/> + <reg32 offset="0x00104" name="RBBM_CLOCK_CNTL_RAC" variants="A6XX-A7XX"/> + <reg32 offset="0x00105" name="RBBM_CLOCK_CNTL2_RAC" variants="A6XX-A7XX"/> + <reg32 offset="0x00106" name="RBBM_CLOCK_DELAY_RAC" variants="A6XX-A7XX"/> + <reg32 offset="0x00107" name="RBBM_CLOCK_HYST_RAC" variants="A6XX-A7XX"/> + <reg32 offset="0x00108" name="RBBM_CLOCK_CNTL_TSE_RAS_RBBM" variants="A6XX-A7XX"/> + <reg32 offset="0x00109" name="RBBM_CLOCK_DELAY_TSE_RAS_RBBM" variants="A6XX-A7XX"/> + <reg32 offset="0x0010a" name="RBBM_CLOCK_HYST_TSE_RAS_RBBM" variants="A6XX-A7XX"/> + <reg32 offset="0x0010b" name="RBBM_CLOCK_CNTL_UCHE" variants="A6XX-A7XX"/> + <reg32 offset="0x0010c" name="RBBM_CLOCK_CNTL2_UCHE" variants="A6XX-A7XX"/> + <reg32 offset="0x0010d" name="RBBM_CLOCK_CNTL3_UCHE" variants="A6XX-A7XX"/> + <reg32 offset="0x0010e" name="RBBM_CLOCK_CNTL4_UCHE" variants="A6XX-A7XX"/> + <reg32 offset="0x0010f" name="RBBM_CLOCK_DELAY_UCHE" variants="A6XX-A7XX"/> + <reg32 offset="0x00110" name="RBBM_CLOCK_HYST_UCHE" variants="A6XX-A7XX"/> + <reg32 offset="0x00111" name="RBBM_CLOCK_MODE_VFD" variants="A6XX-A7XX"/> + <reg32 offset="0x00112" name="RBBM_CLOCK_DELAY_VFD" variants="A6XX-A7XX"/> + <reg32 offset="0x00113" name="RBBM_CLOCK_HYST_VFD" variants="A6XX-A7XX"/> + <reg32 offset="0x00114" name="RBBM_CLOCK_MODE_GPC" variants="A6XX-A7XX"/> + <reg32 offset="0x00115" name="RBBM_CLOCK_DELAY_GPC" variants="A6XX-A7XX"/> + <reg32 offset="0x00116" name="RBBM_CLOCK_HYST_GPC" variants="A6XX-A7XX"/> + <reg32 offset="0x00117" name="RBBM_CLOCK_DELAY_HLSQ_2" variants="A6XX-A7XX"/> + <reg32 offset="0x00118" name="RBBM_CLOCK_CNTL_GMU_GX" variants="A6XX-A7XX"/> + <reg32 offset="0x00119" name="RBBM_CLOCK_DELAY_GMU_GX" variants="A6XX-A7XX"/> + <reg32 offset="0x0011a" name="RBBM_CLOCK_HYST_GMU_GX" variants="A6XX-A7XX"/> + <reg32 offset="0x0011b" name="RBBM_CLOCK_MODE_HLSQ" variants="A6XX-A7XX"/> + <reg32 offset="0x0011c" name="RBBM_CLOCK_DELAY_HLSQ" variants="A6XX-A7XX"/> + <reg32 offset="0x0011d" name="RBBM_CLOCK_HYST_HLSQ" variants="A6XX-A7XX"/> + <reg32 offset="0x0011e" name="RBBM_CGC_GLOBAL_LOAD_CMD" variants="A7XX"/> + <reg32 offset="0x0009b" name="RBBM_CGC_GLOBAL_LOAD_CMD" variants="A8XX-"/> + <reg32 offset="0x0011f" name="RBBM_CGC_P2S_TRIG_CMD" variants="A7XX"/> + <reg32 offset="0x0009c" name="RBBM_CGC_P2S_TRIG_CMD" variants="A8XX-"/> + <reg32 offset="0x00120" name="RBBM_CGC_P2S_CNTL" variants="A7XX"/> + <reg32 offset="0x0009d" name="RBBM_CGC_P2S_CNTL" variants="A8XX-"/> + <reg32 offset="0x00120" name="RBBM_CLOCK_CNTL_TEX_FCHE" variants="A6XX"/> + <reg32 offset="0x00121" name="RBBM_CLOCK_DELAY_TEX_FCHE" variants="A6XX-A7XX"/> + <reg32 offset="0x00122" name="RBBM_CLOCK_HYST_TEX_FCHE" variants="A6XX"/> + <reg32 offset="0x00122" name="RBBM_CGC_P2S_STATUS" variants="A7XX"> + <bitfield name="TXDONE" pos="0" type="boolean"/> + </reg32> + <reg32 offset="0x09f" name="RBBM_CGC_P2S_STATUS" variants="A8XX-"> <bitfield name="TXDONE" pos="0" type="boolean"/> </reg32> - <reg32 offset="0x00123" name="RBBM_CLOCK_CNTL_FCHE"/> - <reg32 offset="0x00124" name="RBBM_CLOCK_DELAY_FCHE"/> - <reg32 offset="0x00125" name="RBBM_CLOCK_HYST_FCHE"/> - <reg32 offset="0x00126" name="RBBM_CLOCK_CNTL_MHUB"/> - <reg32 offset="0x00127" name="RBBM_CLOCK_DELAY_MHUB"/> - <reg32 offset="0x00128" name="RBBM_CLOCK_HYST_MHUB"/> - <reg32 offset="0x00129" name="RBBM_CLOCK_DELAY_GLC"/> - <reg32 offset="0x0012a" name="RBBM_CLOCK_HYST_GLC"/> - <reg32 offset="0x0012b" name="RBBM_CLOCK_CNTL_GLC"/> - <reg32 offset="0x0012f" name="RBBM_CLOCK_HYST2_VFD" variants="A7XX-"/> - <reg32 offset="0x005ff" name="RBBM_LPAC_GBIF_CLIENT_QOS_CNTL"/> + <reg32 offset="0x00123" name="RBBM_CLOCK_CNTL_FCHE" variants="A6XX-A7XX"/> + <reg32 offset="0x00124" name="RBBM_CLOCK_DELAY_FCHE" variants="A6XX-A7XX"/> + <reg32 offset="0x00125" name="RBBM_CLOCK_HYST_FCHE" variants="A6XX-A7XX"/> + <reg32 offset="0x00126" name="RBBM_CLOCK_CNTL_MHUB" variants="A6XX-A7XX"/> + <reg32 offset="0x00127" name="RBBM_CLOCK_DELAY_MHUB" variants="A6XX-A7XX"/> + <reg32 offset="0x00128" name="RBBM_CLOCK_HYST_MHUB" variants="A6XX-A7XX"/> + <reg32 offset="0x00129" name="RBBM_CLOCK_DELAY_GLC" variants="A6XX-A7XX"/> + <reg32 offset="0x0012a" name="RBBM_CLOCK_HYST_GLC" variants="A6XX-A7XX"/> + <reg32 offset="0x0012b" name="RBBM_CLOCK_CNTL_GLC" variants="A6XX-A7XX"/> + <reg32 offset="0x0012f" name="RBBM_CLOCK_HYST2_VFD" variants="A7XX"/> + <reg32 offset="0x00195" name="RBBM_CGC_0_PC" variants="A7XX"/> + <reg32 offset="0x0010b" name="RBBM_CGC_0_PC" variants="A8XX-"/> + + <reg32 offset="0x005ff" name="RBBM_LPAC_GBIF_CLIENT_QOS_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x00009" name="RBBM_LPAC_GBIF_CLIENT_QOS_CNTL" variants="A8XX-"/> <reg32 offset="0x0600" name="DBGC_CFG_DBGBUS_SEL_A"/> <reg32 offset="0x0601" name="DBGC_CFG_DBGBUS_SEL_B"/> <reg32 offset="0x0602" name="DBGC_CFG_DBGBUS_SEL_C"/> - <reg32 offset="0x0603" name="DBGC_CFG_DBGBUS_SEL_D"> + <reg32 offset="0x0603" name="DBGC_CFG_DBGBUS_SEL_D" variants="A6XX"> <bitfield high="7" low="0" name="PING_INDEX"/> <bitfield high="15" low="8" name="PING_BLK_SEL"/> </reg32> + <reg32 offset="0x0603" name="DBGC_CFG_DBGBUS_SEL_D" variants="A7XX-"> + <bitfield high="7" low="0" name="PING_INDEX"/> + <bitfield high="24" low="16" name="PING_BLK_SEL"/> + </reg32> <reg32 offset="0x0604" name="DBGC_CFG_DBGBUS_CNTLT"> <bitfield high="5" low="0" name="TRACEEN"/> <bitfield high="14" low="12" name="GRANU"/> @@ -2810,6 +964,8 @@ to upconvert to 32b float internally? <reg32 offset="0x0605" name="DBGC_CFG_DBGBUS_CNTLM"> <bitfield high="27" low="24" name="ENABLE"/> </reg32> + <reg32 offset="0x0606" name="DBGC_CFG_DBGBUS_OPL"/> + <reg32 offset="0x0607" name="DBGC_CFG_DBGBUS_OPE"/> <reg32 offset="0x0608" name="DBGC_CFG_DBGBUS_IVTL_0"/> <reg32 offset="0x0609" name="DBGC_CFG_DBGBUS_IVTL_1"/> <reg32 offset="0x060a" name="DBGC_CFG_DBGBUS_IVTL_2"/> @@ -2838,72 +994,276 @@ to upconvert to 32b float internally? <bitfield high="27" low="24" name="BYTEL14"/> <bitfield high="31" low="28" name="BYTEL15"/> </reg32> + <reg32 offset="0x0612" name="DBGC_CFG_DBGBUS_IVTE_0"/> + <reg32 offset="0x0613" name="DBGC_CFG_DBGBUS_IVTE_1"/> + <reg32 offset="0x0614" name="DBGC_CFG_DBGBUS_IVTE_2"/> + <reg32 offset="0x0615" name="DBGC_CFG_DBGBUS_IVTE_3"/> + <reg32 offset="0x0616" name="DBGC_CFG_DBGBUS_MASKE_0"/> + <reg32 offset="0x0617" name="DBGC_CFG_DBGBUS_MASKE_1"/> + <reg32 offset="0x0618" name="DBGC_CFG_DBGBUS_MASKE_2"/> + <reg32 offset="0x0619" name="DBGC_CFG_DBGBUS_MASKE_3"/> + <reg32 offset="0x061a" name="DBGC_CFG_DBGBUS_NIBBLEE"/> + <reg32 offset="0x061b" name="DBGC_CFG_DBGBUS_PTRC0"/> + <reg32 offset="0x061c" name="DBGC_CFG_DBGBUS_PTRC1"/> + <reg32 offset="0x061d" name="DBGC_CFG_DBGBUS_LOADREG"/> + <reg32 offset="0x061e" name="DBGC_CFG_DBGBUS_IDX"/> + <reg32 offset="0x061f" name="DBGC_CFG_DBGBUS_CLRC"/> + <reg32 offset="0x0620" name="DBGC_CFG_DBGBUS_LOADIVT"/> + <reg32 offset="0x0621" name="DBGC_VBIF_DBG_CNTL"/> + <reg32 offset="0x0622" name="DBGC_DBG_LO_HI_GPIO"/> + <reg32 offset="0x0623" name="DBGC_EXT_TRACE_BUS_CNTL"/> + <reg32 offset="0x0624" name="DBGC_READ_AHB_THROUGH_DBG"/> + <reg32 offset="0x0625" name="DBGC_CFG_DBGBUS_EVENT_LOGIC"/> + <reg32 offset="0x0626" name="DBGC_CFG_DBGBUS_OVER"/> + <reg32 offset="0x0627" name="DBGC_CFG_DBGBUS_COUNT0"/> + <reg32 offset="0x0628" name="DBGC_CFG_DBGBUS_COUNT1"/> + <reg32 offset="0x0629" name="DBGC_CFG_DBGBUS_COUNT2"/> + <reg32 offset="0x062a" name="DBGC_CFG_DBGBUS_COUNT3"/> + <reg32 offset="0x062b" name="DBGC_CFG_DBGBUS_COUNT4"/> + <reg32 offset="0x062c" name="DBGC_CFG_DBGBUS_COUNT5"/> + <reg32 offset="0x062d" name="DBGC_CFG_DBGBUS_TRACE_ADDR"/> + <reg32 offset="0x062e" name="DBGC_CFG_DBGBUS_TRACE_BUF0"/> <reg32 offset="0x062f" name="DBGC_CFG_DBGBUS_TRACE_BUF1"/> <reg32 offset="0x0630" name="DBGC_CFG_DBGBUS_TRACE_BUF2"/> + <reg32 offset="0x0631" name="DBGC_CFG_DBGBUS_TRACE_BUF3"/> + <reg32 offset="0x0632" name="DBGC_CFG_DBGBUS_TRACE_BUF4"/> + <reg32 offset="0x0633" name="DBGC_CFG_DBGBUS_MISR0"/> + <reg32 offset="0x0634" name="DBGC_CFG_DBGBUS_MISR1"/> + <reg32 offset="0x0635" name="DBGC_EVT_CFG"/> + <reg32 offset="0x0636" name="DBGC_EVT_INTF_SEL_0"/> + <reg32 offset="0x0637" name="DBGC_EVT_INTF_SEL_1"/> + <reg32 offset="0x0638" name="DBGC_EVT_SLICE_CFG"/> + <reg32 offset="0x0639" name="DBGC_QDSS_TIMESTAMP_0"/> + <reg32 offset="0x063a" name="DBGC_QDSS_TIMESTAMP_1"/> + <reg32 offset="0x063b" name="DBGC_ECO_CNTL"/> + <reg32 offset="0x063c" name="DBGC_AHB_DBG_CNTL"/> + <reg32 offset="0x063d" name="DBGC_EVT_INTF_SEL_2"/> + <reg32 offset="0x0640" name="DBGC_CFG_DBGBUS_PONG_SEL_A"/> + <reg32 offset="0x0641" name="DBGC_CFG_DBGBUS_PONG_SEL_B"/> + <reg32 offset="0x0642" name="DBGC_CFG_DBGBUS_PONG_SEL_C"/> + <reg32 offset="0x0643" name="DBGC_CFG_DBGBUS_PONG_SEL_D"/> + <reg32 offset="0x0644" name="DBGC_CFG_DBGBUS_MISC_MODE"/> + <reg32 offset="0x0650" name="DBGC_EVT_INTF_SEL_3_0"/> + <reg32 offset="0x0651" name="DBGC_EVT_INTF_SEL_3_1"/> + <reg32 offset="0x0652" name="DBGC_EVT_INTF_SEL_3_2"/> + <reg32 offset="0x0653" name="DBGC_EVT_INTF_SEL_3_3"/> + <reg32 offset="0x0654" name="DBGC_EVT_INTF_SEL_3_4"/> + <reg32 offset="0x0655" name="DBGC_EVT_INTF_SEL_3_5"/> + <reg32 offset="0x0660" name="DBGC_TRACE_BUFFER_STATUS"/> + <reg32 offset="0x0661" name="DBGC_TRACE_BUFFER_CMD"/> + <reg32 offset="0x0662" name="DBGC_DBG_TRACE_BUFFER_RD_ADDR"/> + <reg32 offset="0x0663" name="DBGC_DBG_TRACE_BUFFER_RD_DATA"/> + <reg32 offset="0x0664" name="DBGC_TRACE_BUFFER_ATB_RD_STATUS"/> + <reg32 offset="0x0665" name="DBGC_SMMU_FAULT_BLOCK_HALT_CFG"/> + <reg32 offset="0x0666" name="DBGC_DBG_LOPC_SB_RD_ADDR"/> + <reg32 offset="0x0667" name="DBGC_DBG_LOPC_SB_RD_DATA"/> + <reg32 offset="0x0668" name="DBGC_DBG_LOPC_SB_WR_ADDR"/> + <reg32 offset="0x0669" name="DBGC_DBG_LOPC_SB_WR_DATA"/> + <reg32 offset="0x066a" name="DBGC_INTERRUPT_STATUS"/> + <reg64 offset="0x0680" name="DBGC_GBIF_DBG_BASE"/> + <reg32 offset="0x0682" name="DBGC_GBIF_DBG_BUFF_SIZE"/> + <reg32 offset="0x0683" name="DBGC_GBIF_DBG_CNTL"/> + <reg32 offset="0x0684" name="DBGC_GBIF_DBG_CMD"/> + <reg32 offset="0x0685" name="DBGC_GBIF_DBG_STATUS"/> + + <reg32 offset="0x0700" name="DBGC_SCOPE_PERF_COUNTER_CFG_US" variants="A8XX-"/> + <reg32 offset="0x0701" name="DBGC_CFG_PERF_TRIG_CLUSTER_FE_US" variants="A8XX-"/> + <reg32 offset="0x0702" name="DBGC_CFG_PERF_TRIG_CLUSTER_VPC_US" variants="A8XX-"/> + <reg32 offset="0x0703" name="DBGC_CFG_PERF_TRIG_CLUSTER_SP_VS_US" variants="A8XX-"/> + <reg32 offset="0x0704" name="DBGC_CFG_PERF_TRIG_CLUSTER_SP_PS_US" variants="A8XX-"/> + <reg32 offset="0x0707" name="DBGC_CFG_PERF_TRIG_CLUSTER_NONE_US" variants="A8XX-"/> + <reg32 offset="0x0708" name="DBGC_CFG_BV_PERF_TRIG_CLUSTER_FE_US" variants="A8XX-"/> + <reg32 offset="0x0709" name="DBGC_CFG_BV_PERF_TRIG_CLUSTER_VPC_US" variants="A8XX-"/> + <reg32 offset="0x070a" name="DBGC_CFG_BV_PERF_TRIG_CLUSTER_SP_VS_US" variants="A8XX-"/> + <reg32 offset="0x070f" name="DBGC_CFG_BV_PERF_TRIG_CLUSTER_NONE_US" variants="A8XX-"/> + <reg32 offset="0x0710" name="DBGC_CFG_PERF_COUNTER_SEL_FE_US" variants="A8XX-"/> + <reg32 offset="0x0711" name="DBGC_CFG_PERF_COUNTER_SEL_FE_US_1" variants="A8XX-"/> + <reg32 offset="0x0712" name="DBGC_CFG_PERF_COUNTER_SEL_FE_US_2" variants="A8XX-"/> + <reg32 offset="0x0713" name="DBGC_CFG_PERF_COUNTER_SEL_VPC_US" variants="A8XX-"/> + <reg32 offset="0x0714" name="DBGC_CFG_PERF_COUNTER_SEL_VPC_US_1" variants="A8XX-"/> + <reg32 offset="0x0715" name="DBGC_CFG_PERF_COUNTER_SEL_SP_VS_US" variants="A8XX-"/> + <reg32 offset="0x0716" name="DBGC_CFG_PERF_COUNTER_SEL_SP_PS_US" variants="A8XX-"/> + <reg32 offset="0x0720" name="DBGC_CFG_PERF_COUNTER_SEL_NONE_US" variants="A8XX-"/> + <reg32 offset="0x0721" name="DBGC_CFG_PERF_COUNTER_SEL_NONE_US_1" variants="A8XX-"/> + <reg32 offset="0x0722" name="DBGC_CFG_BV_PERF_COUNTER_SEL_FE_US" variants="A8XX-"/> + <reg32 offset="0x0723" name="DBGC_CFG_BV_PERF_COUNTER_SEL_FE_US_1" variants="A8XX-"/> + <reg32 offset="0x0724" name="DBGC_CFG_BV_PERF_COUNTER_SEL_FE_US_2" variants="A8XX-"/> + <reg32 offset="0x0730" name="DBGC_CFG_BV_PERF_COUNTER_SEL_VPC_US" variants="A8XX-"/> + <reg32 offset="0x0731" name="DBGC_CFG_BV_PERF_COUNTER_SEL_VPC_US_1" variants="A8XX-"/> + <reg32 offset="0x0732" name="DBGC_CFG_BV_PERF_COUNTER_SEL_SP_VS_US" variants="A8XX-"/> + <reg32 offset="0x0740" name="DBGC_CFG_BV_PERF_COUNTER_SEL_NONE_US" variants="A8XX-"/> + <reg32 offset="0x0742" name="DBGC_CFG_PERF_TIMESTAMP_TRIG_SEL_US" variants="A8XX-"/> + <reg32 offset="0x0743" name="DBGC_CFG_BV_PERF_TIMESTAMP_TRIG_SEL_US" variants="A8XX-"/> + <reg64 offset="0x0744" name="DBGC_CFG_GBIF_BR_PERF_CNTR_BASE" variants="A8XX-"/> + <reg32 offset="0x0746" name="DBGC_CFG_GBIF_BR_BUFFER_SIZE" variants="A8XX-"/> + <reg64 offset="0x0747" name="DBGC_CFG_GBIF_BV_PERF_CNTR_BASE" variants="A8XX-"/> + <reg32 offset="0x0749" name="DBGC_CFG_GBIF_BV_BUFFER_SIZE" variants="A8XX-"/> + <reg32 offset="0x074a" name="DBGC_CFG_GBIF_QOS_CTRL" variants="A8XX-"/> + <reg32 offset="0x0750" name="DBGC_GBIF_BR_PERF_CNTR_WRITE_POINTER" variants="A8XX-"/> + <reg32 offset="0x0751" name="DBGC_GBIF_BV_PERF_CNTR_WRITE_POINTER" variants="A8XX-"/> + <reg32 offset="0x0752" name="DBGC_PERF_COUNTER_FE_LOCAL_BATCH_ID" variants="A8XX-"/> + <reg32 offset="0x0753" name="DBGC_CFG_PERF_WAIT_IDLE_CLOCKS_CNTL" variants="A8XX-"/> + <reg32 offset="0x0754" name="DBGC_PERF_COUNTER_SCOPING_CMD_US" variants="A8XX-"/> + <reg32 offset="0x0755" name="DBGC_PERF_SKEW_BUFFER_INIT_CMD" variants="A8XX-"/> + <reg32 offset="0x0759" name="DBGC_LOPC_INTERRUPT_STATUS" variants="A8XX-"/> + <reg32 offset="0x075a" name="DBGC_LOPC_BUFFER_PTR_STATUS" variants="A8XX-"/> + <reg32 offset="0x075b" name="DBGC_PERF_SCOPING_STATUS" variants="A8XX-"/> + <reg32 offset="0x075c" name="DBGC_PERF_COUNTER_PKT_STATUS" variants="A8XX-"/> + <reg32 offset="0x0760" name="DBGC_GC_LIVE_MBX_PKT_STATUS" variants="A8XX-"/> + <reg32 offset="0x0761" name="DBGC_GC_ALW_MBX_PKT_STATUS" variants="A8XX-"/> + <reg32 offset="0x0762" name="DBGC_AO_CNTR_LO_STATUS" variants="A8XX-"/> + <reg32 offset="0x0763" name="DBGC_AO_CNTR_HI_STATUS" variants="A8XX-"/> + <reg32 offset="0x0770" name="DBGC_LOPC_GC_SB_DEPTH_STATUS" variants="A8XX-"/> + <reg32 offset="0x0780" name="DBGC_LPAC_SCOPE_PERF_COUNTER_CFG_US" variants="A8XX-"/> + <reg32 offset="0x0781" name="DBGC_CFG_PERF_TRIG_LPAC_US" variants="A8XX-"/> + <reg32 offset="0x0782" name="DBGC_CFG_PERF_COUNTER_SEL_LPAC_US" variants="A8XX-"/> + <reg32 offset="0x0783" name="DBGC_CFG_PERF_COUNTER_SEL_LPAC_US_1" variants="A8XX-"/> + <reg32 offset="0x0784" name="DBGC_CFG_PERF_COUNTER_SEL_LPAC_US_2" variants="A8XX-"/> + <reg32 offset="0x0785" name="DBGC_CFG_PERF_TIMESTAMP_TRIG_SEL_LPAC_US" variants="A8XX-"/> + <reg64 offset="0x0786" name="DBGC_CFG_GBIF_LPAC_PERF_CNTR_BASE" variants="A8XX-"/> + <reg32 offset="0x0788" name="DBGC_CFG_GBIF_LPAC_BUFFER_SIZE" variants="A8XX-"/> + <reg32 offset="0x0789" name="DBGC_GBIF_LPAC_PERF_CNTR_WRITE_POINTER" variants="A8XX-"/> + <reg32 offset="0x078a" name="DBGC_CFG_LPAC_PERF_WAIT_IDLE_CLOCKS_CNTL" variants="A8XX-"/> + <reg32 offset="0x078b" name="DBGC_LPAC_PERF_COUNTER_SCOPING_CMD_US" variants="A8XX-"/> + <reg32 offset="0x078c" name="DBGC_LPAC_MBX_PKT_STATUS" variants="A8XX-"/> + <reg32 offset="0x078d" name="DBGC_LPAC_PERF_SCOPING_STATUS" variants="A8XX-"/> + <reg32 offset="0x0790" name="DBGC_LOPC_LPAC_SB_DEPTH_STATUS" variants="A8XX-"/> + <reg32 offset="0x07a0" name="DBGC_SCOPE_PERF_COUNTER_CFG_S" variants="A8XX-"/> + <reg32 offset="0x07a1" name="DBGC_CFG_PERF_TRIG_CLUSTER_FE_S" variants="A8XX-"/> + <reg32 offset="0x07a2" name="DBGC_CFG_PERF_TRIG_CLUSTER_SP_VS" variants="A8XX-"/> + <reg32 offset="0x07a3" name="DBGC_CFG_PERF_TRIG_CLUSTER_VPC_VS" variants="A8XX-"/> + <reg32 offset="0x07a4" name="DBGC_CFG_PERF_TRIG_CLUSTER_GRAS" variants="A8XX-"/> + <reg32 offset="0x07a5" name="DBGC_CFG_PERF_TRIG_CLUSTER_SP_PS" variants="A8XX-"/> + <reg32 offset="0x07a6" name="DBGC_CFG_PERF_TRIG_CLUSTER_VPC_PS" variants="A8XX-"/> + <reg32 offset="0x07a7" name="DBGC_CFG_PERF_TRIG_CLUSTER_PS" variants="A8XX-"/> + <reg32 offset="0x07a8" name="DBGC_CFG_BV_PERF_TRIG_CLUSTER_FE_S" variants="A8XX-"/> + <reg32 offset="0x07a9" name="DBGC_CFG_BV_PERF_TRIG_CLUSTER_SP_VS" variants="A8XX-"/> + <reg32 offset="0x07aa" name="DBGC_CFG_BV_PERF_TRIG_CLUSTER_VPC_VS" variants="A8XX-"/> + <reg32 offset="0x07ab" name="DBGC_CFG_BV_PERF_TRIG_CLUSTER_GRAS" variants="A8XX-"/> + <reg32 offset="0x07ac" name="DBGC_CFG_BV_PERF_TRIG_CLUSTER_VPC_PS" variants="A8XX-"/> + <reg32 offset="0x07ad" name="DBGC_CFG_PERF_COUNTER_SEL_FE_S" variants="A8XX-"/> + <reg32 offset="0x07ae" name="DBGC_CFG_PERF_COUNTER_SEL_FE_S_1" variants="A8XX-"/> + <reg32 offset="0x07af" name="DBGC_CFG_PERF_COUNTER_SEL_FE_S_2" variants="A8XX-"/> + <reg32 offset="0x07b0" name="DBGC_CFG_PERF_COUNTER_SEL_FE_S_3" variants="A8XX-"/> + <reg32 offset="0x07b1" name="DBGC_CFG_PERF_COUNTER_SEL_SP_VS" variants="A8XX-"/> + <reg32 offset="0x07b2" name="DBGC_CFG_PERF_COUNTER_SEL_SP_VS_1" variants="A8XX-"/> + <reg32 offset="0x07b3" name="DBGC_CFG_PERF_COUNTER_SEL_SP_VS_2" variants="A8XX-"/> + <reg32 offset="0x07b4" name="DBGC_CFG_PERF_COUNTER_SEL_SP_VS_3" variants="A8XX-"/> + <reg32 offset="0x07b5" name="DBGC_CFG_PERF_COUNTER_SEL_VPC_VS" variants="A8XX-"/> + <reg32 offset="0x07b6" name="DBGC_CFG_PERF_COUNTER_SEL_VPC_VS_1" variants="A8XX-"/> + <reg32 offset="0x07b7" name="DBGC_CFG_PERF_COUNTER_SEL_GRAS" variants="A8XX-"/> + <reg32 offset="0x07b8" name="DBGC_CFG_PERF_COUNTER_SEL_GRAS_1" variants="A8XX-"/> + <reg32 offset="0x07b9" name="DBGC_CFG_PERF_COUNTER_SEL_GRAS_2" variants="A8XX-"/> + <reg32 offset="0x07ba" name="DBGC_CFG_PERF_COUNTER_SEL_SP_PS" variants="A8XX-"/> + <reg32 offset="0x07bb" name="DBGC_CFG_PERF_COUNTER_SEL_SP_PS_1" variants="A8XX-"/> + <reg32 offset="0x07bc" name="DBGC_CFG_PERF_COUNTER_SEL_SP_PS_2" variants="A8XX-"/> + <reg32 offset="0x07bd" name="DBGC_CFG_PERF_COUNTER_SEL_SP_PS_3" variants="A8XX-"/> + <reg32 offset="0x07be" name="DBGC_CFG_PERF_COUNTER_SEL_VPC_PS" variants="A8XX-"/> + <reg32 offset="0x07bf" name="DBGC_CFG_PERF_COUNTER_SEL_VPC_PS_1" variants="A8XX-"/> + <reg32 offset="0x07c0" name="DBGC_CFG_PERF_COUNTER_SEL_PS" variants="A8XX-"/> + <reg32 offset="0x07c1" name="DBGC_CFG_PERF_COUNTER_SEL_PS_1" variants="A8XX-"/> + <reg32 offset="0x07c2" name="DBGC_CFG_PERF_COUNTER_SEL_PS_2" variants="A8XX-"/> + <reg32 offset="0x07c3" name="DBGC_CFG_PERF_COUNTER_SEL_PS_3" variants="A8XX-"/> + <reg32 offset="0x07c4" name="DBGC_CFG_PERF_TIMESTAMP_TRIG_SEL_S" variants="A8XX-"/> + <reg32 offset="0x07c5" name="DBGC_CFG_BV_PERF_COUNTER_SEL_FE_S" variants="A8XX-"/> + <reg32 offset="0x07c6" name="DBGC_CFG_BV_PERF_COUNTER_SEL_FE_S_1" variants="A8XX-"/> + <reg32 offset="0x07c7" name="DBGC_CFG_BV_PERF_COUNTER_SEL_FE_S_2" variants="A8XX-"/> + <reg32 offset="0x07c8" name="DBGC_CFG_BV_PERF_COUNTER_SEL_FE_S_3" variants="A8XX-"/> + <reg32 offset="0x07c9" name="DBGC_CFG_BV_PERF_COUNTER_SEL_SP_VS" variants="A8XX-"/> + <reg32 offset="0x07ca" name="DBGC_CFG_BV_PERF_COUNTER_SEL_SP_VS_1" variants="A8XX-"/> + <reg32 offset="0x07cb" name="DBGC_CFG_BV_PERF_COUNTER_SEL_SP_VS_2" variants="A8XX-"/> + <reg32 offset="0x07cc" name="DBGC_CFG_BV_PERF_COUNTER_SEL_SP_VS_3" variants="A8XX-"/> + <reg32 offset="0x07cd" name="DBGC_CFG_BV_PERF_COUNTER_SEL_VPC_VS" variants="A8XX-"/> + <reg32 offset="0x07ce" name="DBGC_CFG_BV_PERF_COUNTER_SEL_VPC_VS_1" variants="A8XX-"/> + <reg32 offset="0x07cf" name="DBGC_CFG_BV_PERF_COUNTER_SEL_GRAS" variants="A8XX-"/> + <reg32 offset="0x07d0" name="DBGC_CFG_BV_PERF_COUNTER_SEL_GRAS_1" variants="A8XX-"/> + <reg32 offset="0x07d1" name="DBGC_CFG_BV_PERF_COUNTER_SEL_GRAS_2" variants="A8XX-"/> + <reg32 offset="0x07d2" name="DBGC_CFG_BV_PERF_COUNTER_SEL_VPC_PS" variants="A8XX-"/> + <reg32 offset="0x07d3" name="DBGC_CFG_BV_PERF_COUNTER_SEL_VPC_PS_1" variants="A8XX-"/> + <reg32 offset="0x07d4" name="DBGC_CFG_BV_PERF_TIMESTAMP_TRIG_SEL_S" variants="A8XX-"/> + <reg32 offset="0x07d5" name="DBGC_PERF_COUNTER_SCOPING_CMD_S" variants="A8XX-"/> + <reg32 offset="0x07e0" name="DBGC_LPAC_SCOPE_PERF_COUNTER_CFG_S" variants="A8XX-"/> + <reg32 offset="0x07e1" name="DBGC_CFG_PERF_TRIG_LPAC_S" variants="A8XX-"/> + <reg32 offset="0x07e2" name="DBGC_CFG_PERF_COUNTER_SEL_LPAC_S" variants="A8XX-"/> + <reg32 offset="0x07e3" name="DBGC_CFG_PERF_COUNTER_SEL_LPAC_S_1" variants="A8XX-"/> + <reg32 offset="0x07e4" name="DBGC_CFG_PERF_COUNTER_SEL_LPAC_S_2" variants="A8XX-"/> + <reg32 offset="0x07e5" name="DBGC_CFG_PERF_TIMESTAMP_TRIG_SEL_LPAC_S" variants="A8XX-"/> + <reg32 offset="0x07e6" name="DBGC_LPAC_PERF_COUNTER_SCOPING_CMD_S" variants="A8XX-"/> + <array offset="0x0CD8" name="VSC_PERFCTR_VSC_SEL" stride="1" length="2"/> - <reg32 offset="0x0CD8" name="VSC_UNKNOWN_0CD8" variants="A7XX"> - <doc> - Set to true when binning, isn't changed afterwards - </doc> - <bitfield name="BINNING" pos="0" type="boolean"/> - </reg32> <reg32 offset="0xC800" name="HLSQ_DBG_AHB_READ_APERTURE"/> <reg32 offset="0xD000" name="HLSQ_DBG_READ_SEL"/> - <reg32 offset="0x0E00" name="UCHE_ADDR_MODE_CNTL" type="a5xx_address_mode"/> + <reg32 offset="0x0E00" name="UCHE_ADDR_MODE_CNTL" type="a5xx_address_mode" variants="A6XX"/> <reg32 offset="0x0E01" name="UCHE_MODE_CNTL"/> - <reg64 offset="0x0E05" name="UCHE_WRITE_RANGE_MAX"/> - <reg64 offset="0x0E07" name="UCHE_WRITE_THRU_BASE"/> - <reg64 offset="0x0E09" name="UCHE_TRAP_BASE"/> - <reg64 offset="0x0E0B" name="UCHE_GMEM_RANGE_MIN"/> - <reg64 offset="0x0E0D" name="UCHE_GMEM_RANGE_MAX"/> - <reg32 offset="0x0E17" name="UCHE_CACHE_WAYS" usage="cmd"/> + <reg64 offset="0x0E05" name="UCHE_WRITE_RANGE_MAX" variants="A6XX"/> + <reg64 offset="0x0E07" name="UCHE_WRITE_THRU_BASE" variants="A6XX-A7XX"/> + <reg64 offset="0x0E06" name="UCHE_WRITE_THRU_BASE" variants="A8XX-"/> + <reg64 offset="0x0E09" name="UCHE_TRAP_BASE" variants="A6XX-A7XX"/> + <reg64 offset="0x0E08" name="UCHE_TRAP_BASE" variants="A8XX-"/> + <reg64 offset="0x0E0B" name="UCHE_GMEM_RANGE_MIN" variants="A6XX-A7XX"/> + <reg64 offset="0x0E0D" name="UCHE_GMEM_RANGE_MAX" variants="A6XX-A7XX"/> + <reg32 offset="0x0e17" name="UCHE_CACHE_WAYS" variants="A6XX-A7XX" usage="init"/> + <reg32 offset="0x0e04" name="UCHE_CACHE_WAYS" variants="A8XX-"/> <reg32 offset="0x0E18" name="UCHE_FILTER_CNTL"/> - <reg32 offset="0x0E19" name="UCHE_CLIENT_PF" usage="cmd"> + <reg32 offset="0x0e19" name="UCHE_CLIENT_PF" variants="A6XX-A7XX" usage="init"> <bitfield high="7" low="0" name="PERFSEL"/> </reg32> - <array offset="0x0E1C" name="UCHE_PERFCTR_UCHE_SEL" stride="1" length="12"/> - <reg32 offset="0x0e3a" name="UCHE_GBIF_GX_CONFIG"/> - <reg32 offset="0x0e3c" name="UCHE_CMDQ_CONFIG"/> + <array offset="0x0e1c" name="UCHE_PERFCTR_UCHE_SEL" stride="1" length="12" variants="A6XX-A7XX"/> + <array offset="0x0e20" name="UCHE_PERFCTR_UCHE_SEL" stride="1" length="24" variants="A8XX-"/> + <reg32 offset="0x0e3a" name="UCHE_GBIF_GX_CONFIG" variants="A6XX-A7XX"/> + <reg32 offset="0x0e12" name="UCHE_GBIF_GX_CONFIG" variants="A8XX-"/> + <reg32 offset="0x0e3c" name="UCHE_CMDQ_CONFIG" variants="A6XX-A7XX"/> - <reg32 offset="0x3000" name="VBIF_VERSION"/> - <reg32 offset="0x3001" name="VBIF_CLKON"> + <reg32 offset="0x0f01" name="UCHE_CCHE_MODE_CNTL" variants="A8XX-"/> + <reg32 offset="0x0f02" name="UCHE_CCHE_CACHE_WAYS" variants="A8XX-"/> + <reg64 offset="0x0f04" name="UCHE_CCHE_WRITE_THRU_BASE" variants="A8XX-"/> + <reg64 offset="0x0f06" name="UCHE_CCHE_TRAP_BASE" variants="A8XX-"/> + <reg64 offset="0x0f08" name="UCHE_CCHE_GC_GMEM_RANGE_MIN" variants="A8XX-"/> + <reg64 offset="0x0f0a" name="UCHE_CCHE_LPAC_GMEM_RANGE_MIN" variants="A8XX-"/> + <reg32 offset="0x0f0c" name="UCHE_CCHE_HW_DBG_CNTL" variants="A8XX-"/> + + <!-- VBIF only existed on early a6xx, and was later replaced with GBIF --> + + <reg32 offset="0x3000" name="VBIF_VERSION" variants="A6XX"/> + <reg32 offset="0x3001" name="VBIF_CLKON" variants="A6XX"> <bitfield pos="1" name="FORCE_ON_TESTBUS" type="boolean"/> </reg32> - <reg32 offset="0x302A" name="VBIF_GATE_OFF_WRREQ_EN"/> - <reg32 offset="0x3080" name="VBIF_XIN_HALT_CTRL0"/> - <reg32 offset="0x3081" name="VBIF_XIN_HALT_CTRL1"/> - <reg32 offset="0x3084" name="VBIF_TEST_BUS_OUT_CTRL"/> - <reg32 offset="0x3085" name="VBIF_TEST_BUS1_CTRL0"/> - <reg32 offset="0x3086" name="VBIF_TEST_BUS1_CTRL1"> + <reg32 offset="0x302A" name="VBIF_GATE_OFF_WRREQ_EN" variants="A6XX"/> + <reg32 offset="0x3080" name="VBIF_XIN_HALT_CTRL0" variants="A6XX"/> + <reg32 offset="0x3081" name="VBIF_XIN_HALT_CTRL1" variants="A6XX"/> + <reg32 offset="0x3084" name="VBIF_TEST_BUS_OUT_CTRL" variants="A6XX"/> + <reg32 offset="0x3085" name="VBIF_TEST_BUS1_CTRL0" variants="A6XX"/> + <reg32 offset="0x3086" name="VBIF_TEST_BUS1_CTRL1" variants="A6XX"> <bitfield low="0" high="3" name="DATA_SEL"/> </reg32> - <reg32 offset="0x3087" name="VBIF_TEST_BUS2_CTRL0"/> - <reg32 offset="0x3088" name="VBIF_TEST_BUS2_CTRL1"> + <reg32 offset="0x3087" name="VBIF_TEST_BUS2_CTRL0" variants="A6XX"/> + <reg32 offset="0x3088" name="VBIF_TEST_BUS2_CTRL1" variants="A6XX"> <bitfield low="0" high="8" name="DATA_SEL"/> </reg32> - <reg32 offset="0x308c" name="VBIF_TEST_BUS_OUT"/> - <reg32 offset="0x30d0" name="VBIF_PERF_CNT_SEL0"/> - <reg32 offset="0x30d1" name="VBIF_PERF_CNT_SEL1"/> - <reg32 offset="0x30d2" name="VBIF_PERF_CNT_SEL2"/> - <reg32 offset="0x30d3" name="VBIF_PERF_CNT_SEL3"/> - <reg32 offset="0x30d8" name="VBIF_PERF_CNT_LOW0"/> - <reg32 offset="0x30d9" name="VBIF_PERF_CNT_LOW1"/> - <reg32 offset="0x30da" name="VBIF_PERF_CNT_LOW2"/> - <reg32 offset="0x30db" name="VBIF_PERF_CNT_LOW3"/> - <reg32 offset="0x30e0" name="VBIF_PERF_CNT_HIGH0"/> - <reg32 offset="0x30e1" name="VBIF_PERF_CNT_HIGH1"/> - <reg32 offset="0x30e2" name="VBIF_PERF_CNT_HIGH2"/> - <reg32 offset="0x30e3" name="VBIF_PERF_CNT_HIGH3"/> - <reg32 offset="0x3100" name="VBIF_PERF_PWR_CNT_EN0"/> - <reg32 offset="0x3101" name="VBIF_PERF_PWR_CNT_EN1"/> - <reg32 offset="0x3102" name="VBIF_PERF_PWR_CNT_EN2"/> - <reg32 offset="0x3110" name="VBIF_PERF_PWR_CNT_LOW0"/> - <reg32 offset="0x3111" name="VBIF_PERF_PWR_CNT_LOW1"/> - <reg32 offset="0x3112" name="VBIF_PERF_PWR_CNT_LOW2"/> - <reg32 offset="0x3118" name="VBIF_PERF_PWR_CNT_HIGH0"/> - <reg32 offset="0x3119" name="VBIF_PERF_PWR_CNT_HIGH1"/> - <reg32 offset="0x311a" name="VBIF_PERF_PWR_CNT_HIGH2"/> - + <reg32 offset="0x308c" name="VBIF_TEST_BUS_OUT" variants="A6XX"/> + <reg32 offset="0x30d0" name="VBIF_PERF_CNT_SEL0" variants="A6XX"/> + <reg32 offset="0x30d1" name="VBIF_PERF_CNT_SEL1" variants="A6XX"/> + <reg32 offset="0x30d2" name="VBIF_PERF_CNT_SEL2" variants="A6XX"/> + <reg32 offset="0x30d3" name="VBIF_PERF_CNT_SEL3" variants="A6XX"/> + <reg32 offset="0x30d8" name="VBIF_PERF_CNT_LOW0" variants="A6XX"/> + <reg32 offset="0x30d9" name="VBIF_PERF_CNT_LOW1" variants="A6XX"/> + <reg32 offset="0x30da" name="VBIF_PERF_CNT_LOW2" variants="A6XX"/> + <reg32 offset="0x30db" name="VBIF_PERF_CNT_LOW3" variants="A6XX"/> + <reg32 offset="0x30e0" name="VBIF_PERF_CNT_HIGH0" variants="A6XX"/> + <reg32 offset="0x30e1" name="VBIF_PERF_CNT_HIGH1" variants="A6XX"/> + <reg32 offset="0x30e2" name="VBIF_PERF_CNT_HIGH2" variants="A6XX"/> + <reg32 offset="0x30e3" name="VBIF_PERF_CNT_HIGH3" variants="A6XX"/> + <reg32 offset="0x3100" name="VBIF_PERF_PWR_CNT_EN0" variants="A6XX"/> + <reg32 offset="0x3101" name="VBIF_PERF_PWR_CNT_EN1" variants="A6XX"/> + <reg32 offset="0x3102" name="VBIF_PERF_PWR_CNT_EN2" variants="A6XX"/> + <reg32 offset="0x3110" name="VBIF_PERF_PWR_CNT_LOW0" variants="A6XX"/> + <reg32 offset="0x3111" name="VBIF_PERF_PWR_CNT_LOW1" variants="A6XX"/> + <reg32 offset="0x3112" name="VBIF_PERF_PWR_CNT_LOW2" variants="A6XX"/> + <reg32 offset="0x3118" name="VBIF_PERF_PWR_CNT_HIGH0" variants="A6XX"/> + <reg32 offset="0x3119" name="VBIF_PERF_PWR_CNT_HIGH1" variants="A6XX"/> + <reg32 offset="0x311a" name="VBIF_PERF_PWR_CNT_HIGH2" variants="A6XX"/> + + <reg32 offset="0x3c00" name="GBIF_CX_CONFIG" variants="A8XX-"/> <reg32 offset="0x3c01" name="GBIF_SCACHE_CNTL0"/> <reg32 offset="0x3c02" name="GBIF_SCACHE_CNTL1"/> <reg32 offset="0x3c03" name="GBIF_QSB_SIDE0"/> @@ -2912,32 +1272,68 @@ to upconvert to 32b float internally? <reg32 offset="0x3c06" name="GBIF_QSB_SIDE3"/> <reg32 offset="0x3c45" name="GBIF_HALT"/> <reg32 offset="0x3c46" name="GBIF_HALT_ACK"/> + <reg32 offset="0x3c49" name="GBIF_REINIT_ENABLE" variants="A8XX-"/> + <reg32 offset="0x3c4a" name="GBIF_REINIT_DONE" variants="A8XX-"/> <reg32 offset="0x3cc0" name="GBIF_PERF_PWR_CNT_EN"/> <reg32 offset="0x3cc1" name="GBIF_PERF_PWR_CNT_CLR"/> <reg32 offset="0x3cc2" name="GBIF_PERF_CNT_SEL"/> - <reg32 offset="0x3cc3" name="GBIF_PERF_PWR_CNT_SEL"/> - <reg32 offset="0x3cc4" name="GBIF_PERF_CNT_LOW0"/> - <reg32 offset="0x3cc5" name="GBIF_PERF_CNT_LOW1"/> - <reg32 offset="0x3cc6" name="GBIF_PERF_CNT_LOW2"/> - <reg32 offset="0x3cc7" name="GBIF_PERF_CNT_LOW3"/> - <reg32 offset="0x3cc8" name="GBIF_PERF_CNT_HIGH0"/> - <reg32 offset="0x3cc9" name="GBIF_PERF_CNT_HIGH1"/> - <reg32 offset="0x3cca" name="GBIF_PERF_CNT_HIGH2"/> - <reg32 offset="0x3ccb" name="GBIF_PERF_CNT_HIGH3"/> - <reg32 offset="0x3ccc" name="GBIF_PWR_CNT_LOW0"/> - <reg32 offset="0x3ccd" name="GBIF_PWR_CNT_LOW1"/> - <reg32 offset="0x3cce" name="GBIF_PWR_CNT_LOW2"/> - <reg32 offset="0x3ccf" name="GBIF_PWR_CNT_HIGH0"/> - <reg32 offset="0x3cd0" name="GBIF_PWR_CNT_HIGH1"/> - <reg32 offset="0x3cd1" name="GBIF_PWR_CNT_HIGH2"/> + <reg32 offset="0x3cc3" name="GBIF_PERF_CNT_SEL_1" variants="A8XX-"/> + + <reg32 offset="0x3cc3" name="GBIF_PERF_PWR_CNT_SEL" variants="A6XX-A7XX"/> + <reg32 offset="0x3cc4" name="GBIF_PERF_CNT_LOW0" variants="A6XX-A7XX"/> + <reg32 offset="0x3cc5" name="GBIF_PERF_CNT_LOW1" variants="A6XX-A7XX"/> + <reg32 offset="0x3cc6" name="GBIF_PERF_CNT_LOW2" variants="A6XX-A7XX"/> + <reg32 offset="0x3cc7" name="GBIF_PERF_CNT_LOW3" variants="A6XX-A7XX"/> + <reg32 offset="0x3cc8" name="GBIF_PERF_CNT_HIGH0" variants="A6XX-A7XX"/> + <reg32 offset="0x3cc9" name="GBIF_PERF_CNT_HIGH1" variants="A6XX-A7XX"/> + <reg32 offset="0x3cca" name="GBIF_PERF_CNT_HIGH2" variants="A6XX-A7XX"/> + <reg32 offset="0x3ccb" name="GBIF_PERF_CNT_HIGH3" variants="A6XX-A7XX"/> + <reg32 offset="0x3ccc" name="GBIF_PWR_CNT_LOW0" variants="A6XX-A7XX"/> + <reg32 offset="0x3ccd" name="GBIF_PWR_CNT_LOW1" variants="A6XX-A7XX"/> + <reg32 offset="0x3cce" name="GBIF_PWR_CNT_LOW2" variants="A6XX-A7XX"/> + <reg32 offset="0x3ccf" name="GBIF_PWR_CNT_HIGH0" variants="A6XX-A7XX"/> + <reg32 offset="0x3cd0" name="GBIF_PWR_CNT_HIGH1" variants="A6XX-A7XX"/> + <reg32 offset="0x3cd1" name="GBIF_PWR_CNT_HIGH2" variants="A6XX-A7XX"/> + + <reg32 offset="0x3cc4" name="GBIF_PWR_CNT_SEL" variants="A8XX"/> + <reg32 offset="0x3cc6" name="GBIF_PERF_CNT_LO_0" variants="A8XX"/> + <reg32 offset="0x3cc7" name="GBIF_PERF_CNT_HI_0" variants="A8XX"/> + <reg32 offset="0x3cc8" name="GBIF_PERF_CNT_LO_1" variants="A8XX"/> + <reg32 offset="0x3cc9" name="GBIF_PERF_CNT_HI_1" variants="A8XX"/> + <reg32 offset="0x3cca" name="GBIF_PERF_CNT_LO_2" variants="A8XX"/> + <reg32 offset="0x3ccb" name="GBIF_PERF_CNT_HI_2" variants="A8XX"/> + <reg32 offset="0x3ccc" name="GBIF_PERF_CNT_LO_3" variants="A8XX"/> + <reg32 offset="0x3ccd" name="GBIF_PERF_CNT_HI_3" variants="A8XX"/> + <reg32 offset="0x3cce" name="GBIF_PERF_CNT_LO_4" variants="A8XX"/> + <reg32 offset="0x3ccf" name="GBIF_PERF_CNT_HI_4" variants="A8XX"/> + <reg32 offset="0x3cd0" name="GBIF_PERF_CNT_LO_5" variants="A8XX"/> + <reg32 offset="0x3cd1" name="GBIF_PERF_CNT_HI_5" variants="A8XX"/> + <reg32 offset="0x3cd2" name="GBIF_PERF_CNT_LO_6" variants="A8XX"/> + <reg32 offset="0x3cd3" name="GBIF_PERF_CNT_HI_6" variants="A8XX"/> + <reg32 offset="0x3cd4" name="GBIF_PERF_CNT_LO_7" variants="A8XX"/> + <reg32 offset="0x3cd5" name="GBIF_PERF_CNT_HI_7" variants="A8XX"/> + <reg32 offset="0x3ce0" name="GBIF_PWR_CNT_LO_0" variants="A8XX"/> + <reg32 offset="0x3ce1" name="GBIF_PWR_CNT_LO_1" variants="A8XX"/> + <reg32 offset="0x3ce2" name="GBIF_PWR_CNT_LO_2" variants="A8XX"/> + <reg32 offset="0x3ce3" name="GBIF_PWR_CNT_HI_0" variants="A8XX"/> + <reg32 offset="0x3ce4" name="GBIF_PWR_CNT_HI_1" variants="A8XX"/> + <reg32 offset="0x3ce5" name="GBIF_PWR_CNT_HI_2" variants="A8XX"/> <reg32 offset="0x0c00" name="VSC_DBG_ECO_CNTL"/> - <reg32 offset="0x0c02" name="VSC_BIN_SIZE" usage="rp_blit"> - <bitfield name="WIDTH" low="0" high="7" shr="5" type="uint"/> - <bitfield name="HEIGHT" low="8" high="16" shr="4" type="uint"/> + <reg32 offset="0x0df0" name="VSC_KMD_DBG_ECO_CNTL" variants="A8XX-"/> + <reg32 offset="0x0c02" name="VSC_BIN_SIZE" usage="rp_blit" variants="A6XX-A7XX"> + <bitfield name="BINW" low="0" high="7" shr="5" type="uint"/> + <bitfield name="BINH" low="8" high="16" shr="4" type="uint"/> </reg32> - <reg64 offset="0x0c03" name="VSC_DRAW_STRM_SIZE_ADDRESS" type="waddress" usage="cmd"/> - <reg32 offset="0x0c06" name="VSC_BIN_COUNT" usage="rp_blit"> + + <bitset name="a8xx_bin_size" inline="yes"> + <bitfield name="BINW" low="0" high="9" shr="5" type="uint"/> + <bitfield name="BINH" low="16" high="26" shr="4" type="uint"/> + </bitset> + + <reg32 offset="0x0c02" name="VSC_BIN_SIZE" type="a8xx_bin_size" usage="rp_blit" variants="A8XX"/> + <reg64 offset="0x0c03" name="VSC_SIZE_BASE" type="waddress" usage="cmd"/> + <reg32 offset="0x0c06" name="VSC_EXPANDED_BIN_CNTL" usage="rp_blit"> <bitfield name="NX" low="1" high="10" type="uint"/> <bitfield name="NY" low="11" high="20" type="uint"/> </reg32> @@ -2967,14 +1363,14 @@ to upconvert to 32b float internally? LIMIT is set to PITCH - 64, to make room for a bit of overflow --> - <reg64 offset="0x0c30" name="VSC_PRIM_STRM_ADDRESS" type="waddress" usage="cmd"/> - <reg32 offset="0x0c32" name="VSC_PRIM_STRM_PITCH" usage="cmd"/> - <reg32 offset="0x0c33" name="VSC_PRIM_STRM_LIMIT" usage="cmd"/> - <reg64 offset="0x0c34" name="VSC_DRAW_STRM_ADDRESS" type="waddress" usage="cmd"/> - <reg32 offset="0x0c36" name="VSC_DRAW_STRM_PITCH" usage="cmd"/> - <reg32 offset="0x0c37" name="VSC_DRAW_STRM_LIMIT" usage="cmd"/> - - <array offset="0x0c38" name="VSC_STATE" stride="1" length="32" usage="rp_blit"> + <reg64 offset="0x0c30" name="VSC_PIPE_DATA_PRIM_BASE" type="waddress" usage="cmd"/> + <reg32 offset="0x0c32" name="VSC_PIPE_DATA_PRIM_STRIDE" usage="cmd"/> + <reg32 offset="0x0c33" name="VSC_PIPE_DATA_PRIM_LENGTH" usage="cmd"/> + <reg64 offset="0x0c34" name="VSC_PIPE_DATA_DRAW_BASE" type="waddress" usage="cmd"/> + <reg32 offset="0x0c36" name="VSC_PIPE_DATA_DRAW_STRIDE" usage="cmd"/> + <reg32 offset="0x0c37" name="VSC_PIPE_DATA_DRAW_LENGTH" usage="cmd"/> + + <array offset="0x0c38" name="VSC_CHANNEL_VISIBILITY" stride="1" length="32" usage="rp_blit"> <doc> Seems to be a bitmap of which tiles mapped to the VSC pipe contain geometry. @@ -2985,7 +1381,7 @@ to upconvert to 32b float internally? <reg32 offset="0x0" name="REG"/> </array> - <array offset="0x0c58" name="VSC_PRIM_STRM_SIZE" stride="1" length="32" variants="A6XX" usage="rp_blit"> + <array offset="0x0c58" name="VSC_PIPE_DATA_PRIM_SIZE" stride="1" length="32" variants="A6XX" usage="rp_blit"> <doc> Has the size of data written to corresponding VSC_PRIM_STRM buffer. @@ -2993,20 +1389,24 @@ to upconvert to 32b float internally? <reg32 offset="0x0" name="REG"/> </array> - <array offset="0x0c78" name="VSC_DRAW_STRM_SIZE" stride="1" length="32" variants="A6XX" usage="rp_blit"> + <array offset="0x0c78" name="VSC_PIPE_DATA_DRAW_SIZE" stride="1" length="32" variants="A6XX" usage="rp_blit"> <doc> Has the size of data written to corresponding VSC pipe, ie. - same thing that is written out to VSC_DRAW_STRM_SIZE_ADDRESS_LO/HI + same thing that is written out to VSC_SIZE_BASE </doc> <reg32 offset="0x0" name="REG"/> </array> <reg32 offset="0x0d08" name="VSC_UNKNOWN_0D08" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0x0E10" name="UCHE_UNKNOWN_0E10" variants="A7XX-" usage="cmd"/> - <reg32 offset="0x0E11" name="UCHE_UNKNOWN_0E11" variants="A7XX-" usage="cmd"/> + <reg32 offset="0x0e10" name="UCHE_UNKNOWN_0E10" variants="A7XX" usage="init"/> + <reg32 offset="0x0e10" name="UCHE_VARB_IDLE_TIMEOUT" variants="A8XX-"/> + <reg32 offset="0x0e11" name="UCHE_UNKNOWN_0E11" variants="A7XX" usage="init"/> + <reg32 offset="0x0e11" name="UCHE_CLIENT_PF" variants="A8XX-"/> <!-- always 0x03200000 ? --> - <reg32 offset="0x0e12" name="UCHE_UNKNOWN_0E12" usage="cmd"/> + <reg32 offset="0x0e12" name="UCHE_UNKNOWN_0E12" variants="A6XX-A7XX" usage="init"/> + <reg32 offset="0x0e15" name="UCHE_DBG_ECO_CNTL_0" variants="A8XX-"/> + <reg32 offset="0x0e16" name="UCHE_HW_DBG_CNTL" variants="A8XX-"/> <!-- adreno_reg_xy has 15 bits per coordinate, but a6xx registers only have 14 --> <bitset name="a6xx_reg_xy" inline="yes"> @@ -3014,7 +1414,7 @@ to upconvert to 32b float internally? <bitfield name="Y" low="16" high="29" type="uint"/> </bitset> - <reg32 offset="0x8000" name="GRAS_CL_CNTL" usage="rp_blit"> + <bitset name="a6xx_gras_cl_cntl" inline="yes"> <bitfield name="CLIP_DISABLE" pos="0" type="boolean"/> <bitfield name="ZNEAR_CLIP_DISABLE" pos="1" type="boolean"/> <bitfield name="ZFAR_CLIP_DISABLE" pos="2" type="boolean"/> @@ -3026,19 +1426,34 @@ to upconvert to 32b float internally? <bitfield name="VP_CLIP_CODE_IGNORE" pos="7" type="boolean"/> <bitfield name="VP_XFORM_DISABLE" pos="8" type="boolean"/> <bitfield name="PERSP_DIVISION_DISABLE" pos="9" type="boolean"/> - </reg32> + </bitset> + + <reg32 offset="0x8000" name="GRAS_CL_CNTL" type="a6xx_gras_cl_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8200" name="GRAS_CL_CNTL" type="a6xx_gras_cl_cntl" variants="A8XX-" usage="rp_blit"/> - <bitset name="a6xx_gras_xs_cl_cntl" inline="yes"> + <bitset name="a6xx_gras_xs_clip_cull_distance" inline="yes"> <bitfield name="CLIP_MASK" low="0" high="7"/> <bitfield name="CULL_MASK" low="8" high="15"/> </bitset> - <reg32 offset="0x8001" name="GRAS_VS_CL_CNTL" type="a6xx_gras_xs_cl_cntl" usage="rp_blit"/> - <reg32 offset="0x8002" name="GRAS_DS_CL_CNTL" type="a6xx_gras_xs_cl_cntl" usage="rp_blit"/> - <reg32 offset="0x8003" name="GRAS_GS_CL_CNTL" type="a6xx_gras_xs_cl_cntl" usage="rp_blit"/> - <reg32 offset="0x8004" name="GRAS_MAX_LAYER_INDEX" low="0" high="10" type="uint" usage="rp_blit"/> - - <reg32 offset="0x8005" name="GRAS_CNTL" usage="rp_blit"> - <!-- see also RB_RENDER_CONTROL0 --> + <reg32 offset="0x8001" name="GRAS_CL_VS_CLIP_CULL_DISTANCE" type="a6xx_gras_xs_clip_cull_distance" usage="rp_blit" variants="A6XX-A7XX" /> + <reg32 offset="0x8002" name="GRAS_CL_DS_CLIP_CULL_DISTANCE" type="a6xx_gras_xs_clip_cull_distance" usage="rp_blit" variants="A6XX-A7XX" /> + <reg32 offset="0x8003" name="GRAS_CL_GS_CLIP_CULL_DISTANCE" type="a6xx_gras_xs_clip_cull_distance" usage="rp_blit" variants="A6XX-A7XX" /> + <reg32 offset="0x8004" name="GRAS_CL_ARRAY_SIZE" low="0" high="10" type="uint" usage="rp_blit" variants="A6XX-A7XX" /> + + <reg32 offset="0x8201" name="GRAS_CL_VS_CLIP_CULL_DISTANCE" type="a6xx_gras_xs_clip_cull_distance" usage="rp_blit" variants="A8XX" /> + <reg32 offset="0x8202" name="GRAS_CL_DS_CLIP_CULL_DISTANCE" type="a6xx_gras_xs_clip_cull_distance" usage="rp_blit" variants="A8XX" /> + <reg32 offset="0x8203" name="GRAS_CL_GS_CLIP_CULL_DISTANCE" type="a6xx_gras_xs_clip_cull_distance" usage="rp_blit" variants="A8XX" /> + <reg32 offset="0x8204" name="GRAS_CL_ARRAY_SIZE" low="0" high="10" type="uint" usage="rp_blit" variants="A8XX" /> + + <reg32 offset="0x8228" name="GRAS_UNKNOWN_8228" variants="A8XX-"/> + <reg32 offset="0x8229" name="GRAS_UNKNOWN_8229" variants="A8XX-"/> + <reg32 offset="0x822a" name="GRAS_UNKNOWN_822A" variants="A8XX-"/> + <reg32 offset="0x822b" name="GRAS_UNKNOWN_822B" variants="A8XX-"/> + <reg32 offset="0x822c" name="GRAS_UNKNOWN_822C" variants="A8XX-"/> + <reg32 offset="0x822d" name="GRAS_UNKNOWN_822D" variants="A8XX-"/> + + <bitset name="a6xx_gras_cl_interp_cntl" inline="yes"> + <!-- see also RB_INTERP_CNTL --> <bitfield name="IJ_PERSP_PIXEL" pos="0" type="boolean"/> <bitfield name="IJ_PERSP_CENTROID" pos="1" type="boolean"/> <bitfield name="IJ_PERSP_SAMPLE" pos="2" type="boolean"/> @@ -3048,26 +1463,78 @@ to upconvert to 32b float internally? <bitfield name="COORD_MASK" low="6" high="9" type="hex"/> <bitfield name="UNK10" pos="10" type="boolean" variants="A7XX-"/> <bitfield name="UNK11" pos="11" type="boolean" variants="A7XX-"/> - </reg32> - <reg32 offset="0x8006" name="GRAS_CL_GUARDBAND_CLIP_ADJ" usage="rp_blit"> + </bitset> + + <reg32 offset="0x8005" name="GRAS_CL_INTERP_CNTL" type="a6xx_gras_cl_interp_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8080" name="GRAS_CL_INTERP_CNTL" type="a6xx_gras_cl_interp_cntl" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_gras_cl_guardband_clip_adj" inline="true"> <bitfield name="HORZ" low="0" high="8" type="uint"/> <bitfield name="VERT" low="10" high="18" type="uint"/> - </reg32> + </bitset> - <!-- Something connected to depth-stencil attachment size --> - <reg32 offset="0x8007" name="GRAS_UNKNOWN_8007" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0x8006" name="GRAS_CL_GUARDBAND_CLIP_ADJ" type="a6xx_gras_cl_guardband_clip_adj" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8205" name="GRAS_CL_GUARDBAND_CLIP_ADJ" type="a6xx_gras_cl_guardband_clip_adj" variants="A8XX-" usage="rp_blit"/> + + <!-- the scale/offset is per view, with up to 6 views --> + <bitset name="a6xx_gras_bin_foveat" inline="yes"> + <bitfield name="BINSCALEEN" pos="6" type="boolean"/> + <enum name="a7xx_bin_scale"> + <value value="0" name="NOSCALE"/> + <value value="1" name="SCALE2X"/> + <value value="2" name="SCALE4X"/> + </enum> + <bitfield name="XSCALE_0" low="8" high="9" type="a7xx_bin_scale"/> + <bitfield name="YSCALE_0" low="10" high="11" type="a7xx_bin_scale"/> + <bitfield name="XSCALE_1" low="12" high="13" type="a7xx_bin_scale"/> + <bitfield name="YSCALE_1" low="14" high="15" type="a7xx_bin_scale"/> + <bitfield name="XSCALE_2" low="16" high="17" type="a7xx_bin_scale"/> + <bitfield name="YSCALE_2" low="18" high="19" type="a7xx_bin_scale"/> + <bitfield name="XSCALE_3" low="20" high="21" type="a7xx_bin_scale"/> + <bitfield name="YSCALE_3" low="22" high="23" type="a7xx_bin_scale"/> + <bitfield name="XSCALE_4" low="24" high="25" type="a7xx_bin_scale"/> + <bitfield name="YSCALE_4" low="26" high="27" type="a7xx_bin_scale"/> + <bitfield name="XSCALE_5" low="28" high="29" type="a7xx_bin_scale"/> + <bitfield name="YSCALE_5" low="30" high="31" type="a7xx_bin_scale"/> + </bitset> - <reg32 offset="0x8008" name="GRAS_UNKNOWN_8008" variants="A7XX-" usage="cmd"/> + <reg32 offset="0x8008" name="GRAS_BIN_FOVEAT" type="a6xx_gras_bin_foveat" variants="A7XX" usage="cmd"/> + <reg32 offset="0x8206" name="GRAS_BIN_FOVEAT" type="a6xx_gras_bin_foveat" variants="A8XX-" usage="cmd"/> - <reg32 offset="0x8009" name="GRAS_UNKNOWN_8009" variants="A7XX-" usage="cmd"/> - <reg32 offset="0x800a" name="GRAS_UNKNOWN_800A" variants="A7XX-" usage="cmd"/> - <reg32 offset="0x800b" name="GRAS_UNKNOWN_800B" variants="A7XX-" usage="cmd"/> - <reg32 offset="0x800c" name="GRAS_UNKNOWN_800C" variants="A7XX-" usage="cmd"/> + <reg32 offset="0x8009" name="GRAS_BIN_FOVEAT_OFFSET_0" variants="A7XX-" usage="cmd"> + <bitfield name="XOFFSET_0" low="0" high="9" shr="2" type="uint"/> + <bitfield name="XOFFSET_1" low="10" high="19" shr="2" type="uint"/> + <bitfield name="XOFFSET_2" low="20" high="29" shr="2" type="uint"/> + </reg32> + <reg32 offset="0x800a" name="GRAS_BIN_FOVEAT_OFFSET_1" variants="A7XX-" usage="cmd"> + <bitfield name="XOFFSET_3" low="0" high="9" shr="2" type="uint"/> + <bitfield name="XOFFSET_4" low="10" high="19" shr="2" type="uint"/> + <bitfield name="XOFFSET_5" low="20" high="29" shr="2" type="uint"/> + </reg32> + <reg32 offset="0x800b" name="GRAS_BIN_FOVEAT_OFFSET_2" variants="A7XX-" usage="cmd"> + <bitfield name="YOFFSET_0" low="0" high="9" shr="2" type="uint"/> + <bitfield name="YOFFSET_1" low="10" high="19" shr="2" type="uint"/> + <bitfield name="YOFFSET_2" low="20" high="29" shr="2" type="uint"/> + </reg32> + <reg32 offset="0x800c" name="GRAS_BIN_FOVEAT_OFFSET_3" variants="A7XX-" usage="cmd"> + <bitfield name="YOFFSET_3" low="0" high="9" shr="2" type="uint"/> + <bitfield name="YOFFSET_4" low="10" high="19" shr="2" type="uint"/> + <bitfield name="YOFFSET_5" low="20" high="29" shr="2" type="uint"/> + </reg32> <!-- <reg32 offset="0x80f0" name="GRAS_UNKNOWN_80F0" type="a6xx_reg_xy"/> --> <!-- 0x8006-0x800f invalid --> - <array offset="0x8010" name="GRAS_CL_VPORT" stride="6" length="16" usage="rp_blit"> + <array offset="0x8010" name="GRAS_CL_VIEWPORT" stride="6" length="16" variants="A6XX-A7XX" usage="rp_blit"> + <reg32 offset="0" name="XOFFSET" type="float"/> + <reg32 offset="1" name="XSCALE" type="float"/> + <reg32 offset="2" name="YOFFSET" type="float"/> + <reg32 offset="3" name="YSCALE" type="float"/> + <reg32 offset="4" name="ZOFFSET" type="float"/> + <reg32 offset="5" name="ZSCALE" type="float"/> + </array> + + <array offset="0x82d0" name="GRAS_CL_VIEWPORT" stride="6" length="16" variants="A8XX-" usage="rp_blit"> <reg32 offset="0" name="XOFFSET" type="float"/> <reg32 offset="1" name="XSCALE" type="float"/> <reg32 offset="2" name="YOFFSET" type="float"/> @@ -3075,12 +1542,17 @@ to upconvert to 32b float internally? <reg32 offset="4" name="ZOFFSET" type="float"/> <reg32 offset="5" name="ZSCALE" type="float"/> </array> - <array offset="0x8070" name="GRAS_CL_Z_CLAMP" stride="2" length="16" usage="rp_blit"> + + <array offset="0x8070" name="GRAS_CL_VIEWPORT_ZCLAMP" stride="2" length="16" variants="A6XX-A7XX" usage="rp_blit"> + <reg32 offset="0" name="MIN" type="float"/> + <reg32 offset="1" name="MAX" type="float"/> + </array> + <array offset="0x80c0" name="GRAS_CL_VIEWPORT_ZCLAMP" stride="2" length="16" variants="A8XX-" usage="rp_blit"> <reg32 offset="0" name="MIN" type="float"/> <reg32 offset="1" name="MAX" type="float"/> </array> - <reg32 offset="0x8090" name="GRAS_SU_CNTL" usage="rp_blit"> + <bitset name="a6xx_gras_su_cntl" varset="chip"> <bitfield name="CULL_FRONT" pos="0" type="boolean"/> <bitfield name="CULL_BACK" pos="1" type="boolean"/> <bitfield name="FRONT_CW" pos="2" type="boolean"/> @@ -3090,57 +1562,124 @@ to upconvert to 32b float internally? <bitfield name="LINE_MODE" pos="13" type="a5xx_line_mode"/> <bitfield name="UNK15" low="15" high="16"/> <!-- - On gen1 only MULTIVIEW_ENABLE exists. On gen3 we have - the ability to add the view index to either the RT array - index or the viewport index, and it seems that - MULTIVIEW_ENABLE doesn't do anything, instead we need to - set at least one of RENDERTARGETINDEXINCR or - VIEWPORTINDEXINCR to enable multiview. The blob still - sets MULTIVIEW_ENABLE regardless. - TODO: what about gen2 (a640)? + On gen1 only MULTIVIEW_ENABLE exists. On gen3 we have + the ability to add the view index to either the RT array + index or the viewport index, and it seems that + MULTIVIEW_ENABLE doesn't do anything, instead we need to + set at least one of RENDERTARGETINDEXINCR or + VIEWPORTINDEXINCR to enable multiview. The blob still + sets MULTIVIEW_ENABLE regardless. + TODO: what about gen2 (a640)? --> <bitfield name="MULTIVIEW_ENABLE" pos="17" type="boolean"/> + <bitfield name="RENDERTARGETINDEXINCR" pos="18" type="boolean" variants="A6XX-A7XX"/> + <bitfield name="VIEWPORTINDEXINCR" pos="19" type="boolean" variants="A6XX-A7XX"/> + <bitfield name="UNK20" low="20" high="22" variants="A6XX-A7XX"/> + </bitset> + <reg32 offset="0x8090" name="GRAS_SU_CNTL" type="a6xx_gras_su_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8209" name="GRAS_SU_CNTL" type="a6xx_gras_su_cntl" variants="A8XX-" usage="rp_blit"/> + + <!-- Fields moved from GRAS_SU_CNTL on earlier gens: --> + <reg32 offset="0x820c" name="GRAS_SU_STEREO_CNTL" variants="A8XX-" usage="rp_blit"> <bitfield name="RENDERTARGETINDEXINCR" pos="18" type="boolean"/> <bitfield name="VIEWPORTINDEXINCR" pos="19" type="boolean"/> - <bitfield name="UNK20" low="20" high="22"/> </reg32> - <reg32 offset="0x8091" name="GRAS_SU_POINT_MINMAX" usage="rp_blit"> + + <bitset name="a6xx_gras_su_point_minmax" inline="yes"> <bitfield name="MIN" low="0" high="15" type="ufixed" radix="4"/> <bitfield name="MAX" low="16" high="31" type="ufixed" radix="4"/> - </reg32> - <reg32 offset="0x8092" name="GRAS_SU_POINT_SIZE" low="0" high="15" type="fixed" radix="4" usage="rp_blit"/> + </bitset> + + <reg32 offset="0x8091" name="GRAS_SU_POINT_MINMAX" type="a6xx_gras_su_point_minmax" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x820a" name="GRAS_SU_POINT_MINMAX" type="a6xx_gras_su_point_minmax" variants="A8XX-" usage="rp_blit"/> + + <reg32 offset="0x8092" name="GRAS_SU_POINT_SIZE" low="0" high="15" type="fixed" radix="4" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x820b" name="GRAS_SU_POINT_SIZE" low="0" high="15" type="fixed" radix="4" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_gras_su_depth_cntl" inline="yes"> + <bitfield name="Z_TEST_ENABLE" pos="0" type="boolean"/> + </bitset> + + <reg32 offset="0x8114" name="GRAS_SU_DEPTH_CNTL" variants="A6XX-A7XX" type="a6xx_gras_su_depth_cntl" usage="rp_blit"/> + <reg32 offset="0x8086" name="GRAS_SU_DEPTH_CNTL" variants="A8XX-" type="a6xx_gras_su_depth_cntl" usage="rp_blit"/> + + <bitset name="a6xx_gras_su_stencil_cntl" inline="yes"> + <bitfield name="STENCIL_ENABLE" pos="0" type="boolean"/> + </bitset> + + <reg32 offset="0x8115" name="GRAS_SU_STENCIL_CNTL" type="a6xx_gras_su_stencil_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8087" name="GRAS_SU_STENCIL_CNTL" type="a6xx_gras_su_stencil_cntl" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_gras_su_render_cntl" inline="yes"> + <bitfield name="FS_DISABLE" pos="7" type="boolean"/> + </bitset> + + <reg32 offset="0x8116" name="GRAS_SU_RENDER_CNTL" type="a6xx_gras_su_render_cntl" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x8088" name="GRAS_SU_RENDER_CNTL" type="a6xx_gras_su_render_cntl" variants="A8XX-" usage="rp_blit"/> + <!-- 0x8093 invalid --> - <reg32 offset="0x8094" name="GRAS_SU_DEPTH_PLANE_CNTL" usage="rp_blit"> + <bitset name="a6xx_depth_plane_cntl" inline="yes"> <bitfield name="Z_MODE" low="0" high="1" type="a6xx_ztest_mode"/> - </reg32> - <reg32 offset="0x8095" name="GRAS_SU_POLY_OFFSET_SCALE" type="float" usage="rp_blit"/> - <reg32 offset="0x8096" name="GRAS_SU_POLY_OFFSET_OFFSET" type="float" usage="rp_blit"/> - <reg32 offset="0x8097" name="GRAS_SU_POLY_OFFSET_OFFSET_CLAMP" type="float" usage="rp_blit"/> - <!-- duplicates RB_DEPTH_BUFFER_INFO: --> - <reg32 offset="0x8098" name="GRAS_SU_DEPTH_BUFFER_INFO" usage="rp_blit"> + </bitset> + + <reg32 offset="0x8094" name="GRAS_SU_DEPTH_PLANE_CNTL" type="a6xx_depth_plane_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8089" name="GRAS_SU_DEPTH_PLANE_CNTL" type="a6xx_depth_plane_cntl" variants="A8XX-" usage="rp_blit"/> + + <reg32 offset="0x8095" name="GRAS_SU_POLY_OFFSET_SCALE" type="float" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x808a" name="GRAS_SU_POLY_OFFSET_SCALE" type="float" variants="A8XX-" usage="rp_blit"/> + + <reg32 offset="0x8096" name="GRAS_SU_POLY_OFFSET_OFFSET" type="float" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x808b" name="GRAS_SU_POLY_OFFSET_OFFSET" type="float" variants="A8XX-" usage="rp_blit"/> + + <reg32 offset="0x8097" name="GRAS_SU_POLY_OFFSET_OFFSET_CLAMP" type="float" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x808c" name="GRAS_SU_POLY_OFFSET_OFFSET_CLAMP" type="float" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_depth_buffer_info" inline="yes"> <bitfield name="DEPTH_FORMAT" low="0" high="2" type="a6xx_depth_format"/> - <bitfield name="UNK3" pos="3"/> - </reg32> + <bitfield name="READ_ONLY" pos="3" type="boolean"/> + </bitset> - <reg32 offset="0x8099" name="GRAS_SU_CONSERVATIVE_RAS_CNTL" usage="cmd"> + <!-- duplicates RB_DEPTH_BUFFER_INFO: --> + <reg32 offset="0x8098" name="GRAS_SU_DEPTH_BUFFER_INFO" type="a6xx_depth_buffer_info" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x808d" name="GRAS_SU_DEPTH_BUFFER_INFO" type="a6xx_depth_buffer_info" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_gras_su_conservative_ras_cntl" inline="yes"> <bitfield name="CONSERVATIVERASEN" pos="0" type="boolean"/> - <bitfield name="SHIFTAMOUNT" low="1" high="2"/> + <enum name="a6xx_shift_amount"> + <value value="0" name="NO_SHIFT"/> + <value value="1" name="HALF_PIXEL_SHIFT"/> + <value value="2" name="FULL_PIXEL_SHIFT"/> + </enum> + <bitfield name="SHIFTAMOUNT" low="1" high="2" type="a6xx_shift_amount"/> <bitfield name="INNERCONSERVATIVERASEN" pos="3" type="boolean"/> <bitfield name="UNK4" low="4" high="5"/> - </reg32> + </bitset> + + <reg32 offset="0x8099" name="GRAS_SU_CONSERVATIVE_RAS_CNTL" type="a6xx_gras_su_conservative_ras_cntl" variants="A6XX-A7XX" usage="cmd"/> + <reg32 offset="0x820d" name="GRAS_SU_CONSERVATIVE_RAS_CNTL" type="a6xx_gras_su_conservative_ras_cntl" variants="A8XX-" usage="cmd"/> + <reg32 offset="0x809a" name="GRAS_SU_PATH_RENDERING_CNTL"> <bitfield name="UNK0" pos="0" type="boolean"/> <bitfield name="LINELENGTHEN" pos="1" type="boolean"/> </reg32> - <bitset name="a6xx_gras_layer_cntl" inline="yes"> + <bitset name="a6xx_gras_us_xs_siv_cntl" inline="yes"> <bitfield name="WRITES_LAYER" pos="0" type="boolean"/> <bitfield name="WRITES_VIEW" pos="1" type="boolean"/> </bitset> - <reg32 offset="0x809b" name="GRAS_VS_LAYER_CNTL" type="a6xx_gras_layer_cntl" usage="rp_blit"/> - <reg32 offset="0x809c" name="GRAS_GS_LAYER_CNTL" type="a6xx_gras_layer_cntl" usage="rp_blit"/> - <reg32 offset="0x809d" name="GRAS_DS_LAYER_CNTL" type="a6xx_gras_layer_cntl" usage="rp_blit"/> - <!-- 0x809e/0x809f invalid --> + <reg32 offset="0x809b" name="GRAS_SU_VS_SIV_CNTL" type="a6xx_gras_us_xs_siv_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x809c" name="GRAS_SU_GS_SIV_CNTL" type="a6xx_gras_us_xs_siv_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x809d" name="GRAS_SU_DS_SIV_CNTL" type="a6xx_gras_us_xs_siv_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + + <reg32 offset="0x820e" name="GRAS_SU_VS_SIV_CNTL" type="a6xx_gras_us_xs_siv_cntl" variants="A8XX" usage="rp_blit"/> + <reg32 offset="0x820f" name="GRAS_SU_GS_SIV_CNTL" type="a6xx_gras_us_xs_siv_cntl" variants="A8XX" usage="rp_blit"/> + <reg32 offset="0x8210" name="GRAS_SU_DS_SIV_CNTL" type="a6xx_gras_us_xs_siv_cntl" variants="A8XX" usage="rp_blit"/> + + <bitset name="a6xx_rast_cntl" inline="yes"> + <bitfield name="MODE" low="0" high="1" type="a6xx_polygon_mode"/> + </bitset> + + <reg32 offset="0x8211" name="GRAS_RAST_CNTL" type="a6xx_rast_cntl" variants="A8XX-" usage="rp_blit"/> <enum name="a6xx_sequenced_thread_dist"> <value value="0x0" name="DIST_SCREEN_COORD"/> @@ -3188,8 +1727,7 @@ to upconvert to 32b float internally? <value value="0x3" name="RB_BT"/> </enum> - <reg32 offset="0x80a0" name="GRAS_SC_CNTL" usage="rp_blit"> - <bitfield name="CCUSINGLECACHELINESIZE" low="0" high="2"/> + <bitset name="a6xx_gras_sc_cntl" inline="yes"> <bitfield name="SINGLE_PRIM_MODE" low="3" high="4" type="a6xx_single_prim_mode"/> <bitfield name="RASTER_MODE" pos="5" type="a6xx_raster_mode"/> <bitfield name="RASTER_DIRECTION" low="6" high="7" type="a6xx_raster_direction"/> @@ -3198,7 +1736,12 @@ to upconvert to 32b float internally? <bitfield name="UNK9" pos="9" type="boolean"/> <bitfield name="ROTATION" low="10" high="11" type="uint"/> <bitfield name="EARLYVIZOUTEN" pos="12" type="boolean"/> + </bitset> + + <reg32 offset="0x80a0" name="GRAS_SC_CNTL" type="a6xx_gras_sc_cntl" variants="A6XX-A7XX" usage="rp_blit"> + <bitfield name="CCUSINGLECACHELINESIZE" low="0" high="2" variants="A6XX-A7XX"/> </reg32> + <reg32 offset="0x8230" name="GRAS_SC_CNTL" type="a6xx_gras_sc_cntl" variants="A8XX-" usage="rp_blit"/> <enum name="a6xx_render_mode"> <value value="0x0" name="RENDERING_PASS"/> @@ -3213,13 +1756,13 @@ to upconvert to 32b float internally? <enum name="a6xx_lrz_feedback_mask"> <value value="0x0" name="LRZ_FEEDBACK_NONE"/> <value value="0x1" name="LRZ_FEEDBACK_EARLY_Z"/> - <value value="0x2" name="LRZ_FEEDBACK_EARLY_LRZ_LATE_Z"/> + <value value="0x2" name="LRZ_FEEDBACK_EARLY_Z_LATE_Z"/> <!-- We don't have a flag type and this flags combination is often used --> - <value value="0x3" name="LRZ_FEEDBACK_EARLY_Z_OR_EARLY_LRZ_LATE_Z"/> + <value value="0x3" name="LRZ_FEEDBACK_EARLY_Z_OR_EARLY_Z_LATE_Z"/> <value value="0x4" name="LRZ_FEEDBACK_LATE_Z"/> </enum> - <reg32 offset="0x80a1" name="GRAS_BIN_CONTROL" usage="rp_blit"> + <bitset name="a6xx_bin_cntl" inline="yes"> <bitfield name="BINW" low="0" high="5" shr="5" type="uint"/> <bitfield name="BINH" low="8" high="14" shr="4" type="uint"/> <bitfield name="RENDER_MODE" low="18" high="20" type="a6xx_render_mode"/> @@ -3232,25 +1775,56 @@ to upconvert to 32b float internally? In sysmem mode GRAS_LRZ_CNTL.LRZ_WRITE is not considered. </doc> <bitfield name="LRZ_FEEDBACK_ZMODE_MASK" low="24" high="26" type="a6xx_lrz_feedback_mask"/> - <bitfield name="UNK27" pos="27"/> + <bitfield name="FORCE_LRZ_DIS" pos="27" type="boolean"/> + </bitset> + + <reg32 offset="0x80a1" name="GRAS_SC_BIN_CNTL" type="a6xx_bin_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + + <!-- Common fields for RB_CNTL and GRAS_SC_BIN_CNTL --> + <bitset name="a8xx_bin_cntl" inline="yes"> + <bitfield name="BINW" low="0" high="9" shr="5" type="uint"/> + <bitfield name="BINH" low="16" high="26" shr="4" type="uint"/> + <bitfield name="RENDER_MODE" low="11" high="13" type="a6xx_render_mode"/> + <doc> + Allows draws that don't have GRAS_LRZ_CNTL.LRZ_WRITE but have + GRAS_LRZ_CNTL.ENABLE to contribute to LRZ during RENDERING pass. + In sysmem mode GRAS_LRZ_CNTL.LRZ_WRITE is not considered. + </doc> + <bitfield name="LRZ_FEEDBACK_ZMODE_MASK" low="28" high="30" type="a6xx_lrz_feedback_mask"/> + <doc>Disable LRZ feedback writes</doc> + <bitfield name="FORCE_LRZ_WRITE_DIS" pos="31" type="boolean"/> + </bitset> + + <reg32 offset="0x8231" name="GRAS_SC_BIN_CNTL" type="a8xx_bin_cntl" variants="A8XX-" usage="rp_blit"> + <bitfield name="CONS_VIS_IN_BINNING" pos="10" type="boolean"/> + <bitfield name="FORCE_BI_DIR_LRZ_DISABLE" pos="14" type="boolean"/> + <bitfield name="FORCE_LRZ_DIS" pos="15" type="boolean"/> + <bitfield name="BIN_VRS_DIS" pos="27" type="boolean"/> </reg32> - <reg32 offset="0x80a2" name="GRAS_RAS_MSAA_CNTL" usage="rp_blit"> + <bitset name="a6xx_gras_sc_ras_msaa_cntl" inline="yes"> <bitfield name="SAMPLES" low="0" high="1" type="a3xx_msaa_samples"/> <bitfield name="UNK2" pos="2"/> <bitfield name="UNK3" pos="3"/> - </reg32> - <reg32 offset="0x80a3" name="GRAS_DEST_MSAA_CNTL" usage="rp_blit"> + </bitset> + + <reg32 offset="0x80a2" name="GRAS_SC_RAS_MSAA_CNTL" type="a6xx_gras_sc_ras_msaa_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8232" name="GRAS_SC_RAS_MSAA_CNTL" type="a6xx_gras_sc_ras_msaa_cntl" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_gras_sc_dest_msaa_cntl" inline="yes"> <bitfield name="SAMPLES" low="0" high="1" type="a3xx_msaa_samples"/> <bitfield name="MSAA_DISABLE" pos="2" type="boolean"/> - </reg32> + </bitset> + + <reg32 offset="0x80a3" name="GRAS_SC_DEST_MSAA_CNTL" type="a6xx_gras_sc_dest_msaa_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8233" name="GRAS_SC_DEST_MSAA_CNTL" type="a6xx_gras_sc_dest_msaa_cntl" variants="A8XX-" usage="rp_blit"/> - <bitset name="a6xx_sample_config" inline="yes"> + <bitset name="a6xx_msaa_sample_pos_cntl" inline="yes"> <bitfield name="UNK0" pos="0"/> <bitfield name="LOCATION_ENABLE" pos="1" type="boolean"/> </bitset> - <bitset name="a6xx_sample_locations" inline="yes"> + <bitset name="a6xx_programmable_msaa_pos" inline="yes"> <bitfield name="SAMPLE_0_X" low="0" high="3" radix="4" type="fixed"/> <bitfield name="SAMPLE_0_Y" low="4" high="7" radix="4" type="fixed"/> <bitfield name="SAMPLE_1_X" low="8" high="11" radix="4" type="fixed"/> @@ -3261,38 +1835,103 @@ to upconvert to 32b float internally? <bitfield name="SAMPLE_3_Y" low="28" high="31" radix="4" type="fixed"/> </bitset> - <reg32 offset="0x80a4" name="GRAS_SAMPLE_CONFIG" type="a6xx_sample_config" usage="rp_blit"/> - <reg32 offset="0x80a5" name="GRAS_SAMPLE_LOCATION_0" type="a6xx_sample_locations" usage="rp_blit"/> - <reg32 offset="0x80a6" name="GRAS_SAMPLE_LOCATION_1" type="a6xx_sample_locations" usage="rp_blit"/> + <reg32 offset="0x80a4" name="GRAS_SC_MSAA_SAMPLE_POS_CNTL" type="a6xx_msaa_sample_pos_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x80a5" name="GRAS_SC_PROGRAMMABLE_MSAA_POS_0" type="a6xx_programmable_msaa_pos" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x80a6" name="GRAS_SC_PROGRAMMABLE_MSAA_POS_1" type="a6xx_programmable_msaa_pos" variants="A6XX-A7XX" usage="rp_blit"/> - <reg32 offset="0x80a7" name="GRAS_UNKNOWN_80A7" variants="A7XX-" usage="cmd"/> + <reg32 offset="0x8237" name="GRAS_SC_MSAA_SAMPLE_POS_CNTL" type="a6xx_msaa_sample_pos_cntl" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x8238" name="GRAS_SC_PROGRAMMABLE_MSAA_POS_0" type="a6xx_programmable_msaa_pos" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x8239" name="GRAS_SC_PROGRAMMABLE_MSAA_POS_1" type="a6xx_programmable_msaa_pos" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x823a" name="GRAS_SC_PROGRAMMABLE_MSAA_POS_2" type="a6xx_programmable_msaa_pos" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x823b" name="GRAS_SC_PROGRAMMABLE_MSAA_POS_3" type="a6xx_programmable_msaa_pos" variants="A8XX-" usage="rp_blit"/> - <!-- 0x80a7-0x80ae invalid --> - <reg32 offset="0x80af" name="GRAS_UNKNOWN_80AF" pos="0" usage="cmd"/> + <reg32 offset="0x80a7" name="GRAS_ROTATION_CNTL" variants="A7XX" usage="cmd"/> + <reg32 offset="0x8207" name="GRAS_ROTATION_CNTL" variants="A8XX-" usage="cmd"/> + + <bitset name="a6xx_screen_scissor_cntl" inline="yes"> + <bitfield name="SCISSOR_DISABLE" pos="0" type="boolean"/> + </bitset> + + <reg32 offset="0x80af" name="GRAS_SC_SCREEN_SCISSOR_CNTL" type="a6xx_screen_scissor_cntl" variants="A6XX-A7XX" pos="0" usage="cmd"/> + <reg32 offset="0x8234" name="GRAS_SC_SCREEN_SCISSOR_CNTL" type="a6xx_screen_scissor_cntl" variants="A8XX-" pos="0" usage="cmd"/> <bitset name="a6xx_scissor_xy" inline="yes"> <bitfield name="X" low="0" high="15" type="uint"/> <bitfield name="Y" low="16" high="31" type="uint"/> </bitset> - <array offset="0x80b0" name="GRAS_SC_SCREEN_SCISSOR" stride="2" length="16" usage="rp_blit"> + + <array offset="0x80b0" name="GRAS_SC_SCREEN_SCISSOR" stride="2" length="16" variants="A6XX-A7XX" usage="rp_blit"> + <reg32 offset="0" name="TL" type="a6xx_scissor_xy"/> + <reg32 offset="1" name="BR" type="a6xx_scissor_xy"/> + </array> + + <array offset="0x8240" name="GRAS_SC_SCREEN_SCISSOR" stride="2" length="16" variants="A8XX-" usage="rp_blit"> + <reg32 offset="0" name="TL" type="a6xx_scissor_xy"/> + <reg32 offset="1" name="BR" type="a6xx_scissor_xy"/> + </array> + + <array offset="0x80d0" name="GRAS_SC_VIEWPORT_SCISSOR" stride="2" length="16" variants="A6XX-A7XX" usage="rp_blit"> <reg32 offset="0" name="TL" type="a6xx_scissor_xy"/> <reg32 offset="1" name="BR" type="a6xx_scissor_xy"/> </array> - <array offset="0x80d0" name="GRAS_SC_VIEWPORT_SCISSOR" stride="2" length="16" usage="rp_blit"> + <array offset="0x8270" name="GRAS_SC_VIEWPORT_SCISSOR" stride="2" length="16" variants="A8XX-" usage="rp_blit"> <reg32 offset="0" name="TL" type="a6xx_scissor_xy"/> <reg32 offset="1" name="BR" type="a6xx_scissor_xy"/> </array> - <reg32 offset="0x80f0" name="GRAS_SC_WINDOW_SCISSOR_TL" type="a6xx_reg_xy" usage="rp_blit"/> - <reg32 offset="0x80f1" name="GRAS_SC_WINDOW_SCISSOR_BR" type="a6xx_reg_xy" usage="rp_blit"/> + <reg32 offset="0x80f0" name="GRAS_SC_WINDOW_SCISSOR_TL" type="a6xx_reg_xy" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x80f1" name="GRAS_SC_WINDOW_SCISSOR_BR" type="a6xx_reg_xy" variants="A6XX-A7XX" usage="rp_blit"/> + + <reg32 offset="0x8235" name="GRAS_SC_WINDOW_SCISSOR_TL" type="a6xx_reg_xy" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x8236" name="GRAS_SC_WINDOW_SCISSOR_BR" type="a6xx_reg_xy" variants="A8XX-" usage="rp_blit"/> + + <enum name="a6xx_fsr_combiner"> + <value value="0" name="FSR_COMBINER_OP_KEEP"/> + <value value="1" name="FSR_COMBINER_OP_REPLACE"/> + <value value="2" name="FSR_COMBINER_OP_MIN"/> + <value value="3" name="FSR_COMBINER_OP_MAX"/> + <value value="4" name="FSR_COMBINER_OP_MUL"/> + </enum> + + <bitset name="a6xx_gras_vrs_config"> + <bitfield name="PIPELINE_FSR_ENABLE" pos="0" type="boolean"/> + <bitfield name="FRAG_SIZE_X" low="1" high="2" type="uint"/> + <bitfield name="FRAG_SIZE_Y" low="3" high="4" type="uint"/> + <bitfield name="COMBINER_OP_1" low="5" high="7" type="a6xx_fsr_combiner"/> + <bitfield name="COMBINER_OP_2" low="8" high="10" type="a6xx_fsr_combiner"/> + <bitfield name="ATTACHMENT_FSR_ENABLE" pos="13" type="boolean"/> + <bitfield name="PRIMITIVE_FSR_ENABLE" pos="20" type="boolean"/> + </bitset> + + <reg32 offset="0x80f4" name="GRAS_VRS_CONFIG" type="a6xx_gras_vrs_config" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x8208" name="GRAS_VRS_CONFIG" type="a6xx_gras_vrs_config" variants="A8XX-" usage="rp_blit"/> - <!-- 0x80f4 - 0x80fa are used for VK_KHR_fragment_shading_rate --> - <reg64 offset="0x80f4" name="GRAS_UNKNOWN_80F4" variants="A7XX-" usage="cmd"/> - <reg64 offset="0x80f5" name="GRAS_UNKNOWN_80F5" variants="A7XX-" usage="cmd"/> - <reg64 offset="0x80f6" name="GRAS_UNKNOWN_80F6" variants="A7XX-" usage="cmd"/> - <reg64 offset="0x80f8" name="GRAS_UNKNOWN_80F8" variants="A7XX-" usage="cmd"/> - <reg64 offset="0x80f9" name="GRAS_UNKNOWN_80F9" variants="A7XX-" usage="cmd"/> - <reg64 offset="0x80fa" name="GRAS_UNKNOWN_80FA" variants="A7XX-" usage="cmd"/> + <bitset name="a6xx_gras_quality_buffer_info" inline="yes"> + <bitfield name="LAYERED" pos="0" type="boolean"/> + <bitfield name="TILE_MODE" low="1" high="2" type="a6xx_tile_mode"/> + </bitset> + + <reg32 offset="0x80f5" name="GRAS_QUALITY_BUFFER_INFO" type="a6xx_gras_quality_buffer_info" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x808e" name="GRAS_QUALITY_BUFFER_INFO" type="a6xx_gras_quality_buffer_info" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_gras_quality_buffer_dimension" inline="yes"> + <bitfield name="WIDTH" low="0" high="15" type="uint"/> + <bitfield name="HEIGHT" low="16" high="31" type="uint"/> + </bitset> + + <reg32 offset="0x80f6" name="GRAS_QUALITY_BUFFER_DIMENSION" type="a6xx_gras_quality_buffer_dimension" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x808f" name="GRAS_QUALITY_BUFFER_DIMENSION" type="a6xx_gras_quality_buffer_dimension" variants="A8XX-" usage="rp_blit"/> + + <reg64 offset="0x80f8" name="GRAS_QUALITY_BUFFER_BASE" variants="A7XX" type="waddress" usage="rp_blit"/> + <reg64 offset="0x8090" name="GRAS_QUALITY_BUFFER_BASE" variants="A8XX-" type="waddress" usage="rp_blit"/> + + <bitset name="a6xx_gras_quality_buffer_pitch" inline="yes"> + <bitfield name="PITCH" shr="6" low="0" high="7" type="uint"/> + <bitfield name="ARRAY_PITCH" shr="6" low="10" high="28" type="uint"/> + </bitset> + + <reg32 offset="0x80fa" name="GRAS_QUALITY_BUFFER_PITCH" type="a6xx_gras_quality_buffer_pitch" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x8092" name="GRAS_QUALITY_BUFFER_PITCH" type="a6xx_gras_quality_buffer_pitch" variants="A8XX-" usage="rp_blit"/> <enum name="a6xx_lrz_dir_status"> <value value="0x1" name="LRZ_DIR_LE"/> @@ -3300,7 +1939,7 @@ to upconvert to 32b float internally? <value value="0x3" name="LRZ_DIR_INVALID"/> </enum> - <reg32 offset="0x8100" name="GRAS_LRZ_CNTL" usage="rp_blit"> + <bitset name="a6xx_gras_lrz_cntl" inline="yes"> <bitfield name="ENABLE" pos="0" type="boolean"/> <doc>LRZ write also disabled for blend/etc.</doc> <bitfield name="LRZ_WRITE" pos="1" type="boolean"/> @@ -3311,9 +1950,8 @@ to upconvert to 32b float internally? - 0.0 if GREATER - 1.0 if LESS </doc> - <bitfield name="FC_ENABLE" pos="3" type="boolean" variants="A6XX"/> <!-- set when depth-test + depth-write enabled --> - <bitfield name="Z_TEST_ENABLE" pos="4" type="boolean"/> + <bitfield name="Z_WRITE_ENABLE" pos="4" type="boolean"/> <bitfield name="Z_BOUNDS_ENABLE" pos="5" type="boolean"/> <bitfield name="DIR" low="6" high="7" type="a6xx_lrz_dir_status"/> <doc> @@ -3325,8 +1963,26 @@ to upconvert to 32b float internally? Disable LRZ based on previous direction and the current one. If DIR_WRITE is not enabled - there is no write to direction buffer. </doc> - <bitfield name="DISABLE_ON_WRONG_DIR" pos="9" type="boolean" variants="A6XX"/> <bitfield name="Z_FUNC" low="11" high="13" type="adreno_compare_func" variants="A7XX-"/> + </bitset> + + <reg32 offset="0x8100" name="GRAS_LRZ_CNTL" type="a6xx_gras_lrz_cntl" usage="rp_blit" variants="A6XX"> + <bitfield name="FC_ENABLE" pos="3" type="boolean" variants="A6XX"/> + <bitfield name="DISABLE_ON_WRONG_DIR" pos="9" type="boolean" variants="A6XX"/> + </reg32> + <reg32 offset="0x8100" name="GRAS_LRZ_CNTL" type="a6xx_gras_lrz_cntl" usage="rp_blit" variants="A7XX"/> + <reg32 offset="0x8212" name="GRAS_LRZ_CNTL" type="a6xx_gras_lrz_cntl" usage="rp_blit" variants="A8XX-"/> + + <reg32 offset="0x8007" name="GRAS_LRZ_CB_CNTL" variants="A7XX" usage="rp_blit"> + <doc> + The total size of the LRZ image array (not including + fast clear buffer), used as a stride for double + buffering used with concurrent binning. + </doc> + <bitfield name="DOUBLE_BUFFER_STRIDE" low="8" high="31" shr="8"/> + </reg32> + <reg32 offset="0x8101" name="GRAS_LRZ_CB_CNTL" usage="rp_blit" variants="A8XX-"> + <bitfield name="DOUBLE_BUFFER_PITCH" low="8" high="31" shr="8"/> </reg32> <enum name="a6xx_fragcoord_sample_mode"> @@ -3334,20 +1990,33 @@ to upconvert to 32b float internally? <value value="3" name="FRAGCOORD_SAMPLE"/> </enum> - <reg32 offset="0x8101" name="GRAS_LRZ_PS_INPUT_CNTL" low="0" high="2" usage="rp_blit"> + <bitset name="a6xx_gras_lrz_ps_input_cntl" inline="yes"> <bitfield name="SAMPLEID" pos="0" type="boolean"/> <bitfield name="FRAGCOORDSAMPLEMODE" low="1" high="2" type="a6xx_fragcoord_sample_mode"/> - </reg32> + </bitset> + + <reg32 offset="0x8101" name="GRAS_LRZ_PS_INPUT_CNTL" type="a6xx_gras_lrz_ps_input_cntl" usage="rp_blit" variants="A6XX-A7XX"/> + <reg32 offset="0x8102" name="GRAS_LRZ_PS_INPUT_CNTL" type="a6xx_gras_lrz_ps_input_cntl" usage="rp_blit" variants="A8XX-"/> - <reg32 offset="0x8102" name="GRAS_LRZ_MRT_BUF_INFO_0" usage="rp_blit"> + <bitset name="a6xx_gras_lrz_mrt_buffer_info_0" inline="yes"> <bitfield name="COLOR_FORMAT" low="0" high="7" type="a6xx_format"/> - </reg32> - <reg64 offset="0x8103" name="GRAS_LRZ_BUFFER_BASE" align="256" type="waddress" usage="rp_blit"/> - <reg32 offset="0x8105" name="GRAS_LRZ_BUFFER_PITCH" usage="rp_blit"> - <!-- TODO: fix the shr fields --> + </bitset> + + <reg32 offset="0x8102" name="GRAS_LRZ_MRT_BUFFER_INFO_0" type="a6xx_gras_lrz_mrt_buffer_info_0" usage="rp_blit" variants="A6XX-A7XX"/> + <reg32 offset="0x8103" name="GRAS_LRZ_MRT_BUFFER_INFO_0" type="a6xx_gras_lrz_mrt_buffer_info_0" usage="rp_blit" variants="A8XX-"/> + + <reg64 offset="0x8103" name="GRAS_LRZ_BUFFER_BASE" align="256" type="waddress" usage="rp_blit" variants="A6XX-A7XX"/> + <reg64 offset="0x8104" name="GRAS_LRZ_BUFFER_BASE" align="256" type="waddress" usage="rp_blit" variants="A8XX-"/> + + <bitset name="a6xx_gras_lrz_buffer_pitch" inline="yes"> <bitfield name="PITCH" low="0" high="7" shr="5" type="uint"/> - <bitfield name="ARRAY_PITCH" low="10" high="28" shr="4" type="uint"/> - </reg32> + <bitfield name="ARRAY_PITCH" low="10" high="28" shr="8" type="uint"/> + </bitset> + + <reg32 offset="0x8105" name="GRAS_LRZ_BUFFER_PITCH" type="a6xx_gras_lrz_buffer_pitch" usage="rp_blit" variants="A6XX-A7XX"/> + <reg32 offset="0x8108" name="GRAS_LRZ_BUFFER_PITCH" type="a6xx_gras_lrz_buffer_pitch" usage="rp_blit" variants="A8XX-"/> + + <reg32 offset="0x810e" name="GRAS_LRZ_BUFFER_STRIDE" usage="rp_blit" low="0" high="16" shr="12" variants="A8XX-"/> <!-- The LRZ "fast clear" buffer is initialized to zero's by blob, and @@ -3380,19 +2049,18 @@ to upconvert to 32b float internally? not. --> <reg64 offset="0x8106" name="GRAS_LRZ_FAST_CLEAR_BUFFER_BASE" align="64" type="waddress" usage="rp_blit"/> - <!-- 0x8108 invalid --> - <reg32 offset="0x8109" name="GRAS_SAMPLE_CNTL" usage="rp_blit"> + <reg32 offset="0x8109" name="GRAS_LRZ_PS_SAMPLEFREQ_CNTL" usage="rp_blit"> <bitfield name="PER_SAMP_MODE" pos="0" type="boolean"/> </reg32> <!-- LRZ buffer represents a single array layer + mip level, and there is a single buffer per depth image. Thus to reuse LRZ between renderpasses it is necessary to track the depth view used in the past renderpass, which - GRAS_LRZ_DEPTH_VIEW is for. - GRAS_LRZ_CNTL checks if current value of GRAS_LRZ_DEPTH_VIEW is equal to + GRAS_LRZ_VIEW_INFO is for. + GRAS_LRZ_CNTL checks if current value of GRAS_LRZ_VIEW_INFO is equal to the value stored in the LRZ buffer, if not - LRZ is disabled. --> - <reg32 offset="0x810a" name="GRAS_LRZ_DEPTH_VIEW" usage="cmd"> + <reg32 offset="0x810a" name="GRAS_LRZ_VIEW_INFO" usage="cmd"> <bitfield name="BASE_LAYER" low="0" high="10" type="uint"/> <bitfield name="LAYER_COUNT" low="16" high="26" type="uint"/> <bitfield name="BASE_MIP_LEVEL" low="28" high="31" type="uint"/> @@ -3405,21 +2073,32 @@ to upconvert to 32b float internally? <!-- 0x810c-0x810f invalid --> - <reg32 offset="0x8110" name="GRAS_UNKNOWN_8110" low="0" high="1" usage="cmd"/> + <reg32 offset="0x8110" name="GRAS_LRZ_BUFFER_SLICE_PITCH" low="0" high="31" shr="8" type="uint" variants="A8XX-"/> + + <reg32 offset="0x8110" name="GRAS_MODE_CNTL" low="0" high="1" variants="A6XX-A7XX" usage="cmd"/> + <reg32 offset="0x8213" name="GRAS_MODE_CNTL" low="0" high="1" variants="A8XX-" usage="cmd"/> <!-- A bit tentative but it's a color and it is followed by LRZ_CLEAR --> - <reg32 offset="0x8111" name="GRAS_LRZ_CLEAR_DEPTH_F32" type="float" variants="A7XX-"/> + <reg32 offset="0x8111" name="GRAS_LRZ_DEPTH_CLEAR" type="float" variants="A7XX"/> + <reg32 offset="0x810d" name="GRAS_LRZ_DEPTH_CLEAR" type="float" variants="A8XX-"/> - <reg32 offset="0x8113" name="GRAS_LRZ_DEPTH_BUFFER_INFO" variants="A7XX-" usage="rp_blit"> - <bitfield name="DEPTH_FORMAT" low="0" high="2" type="a6xx_depth_format"/> - <bitfield name="UNK3" pos="3"/> - </reg32> + <reg32 offset="0x8113" name="GRAS_LRZ_DEPTH_BUFFER_INFO" type="a6xx_depth_buffer_info" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x810f" name="GRAS_LRZ_DEPTH_BUFFER_INFO" type="a6xx_depth_buffer_info" variants="A8XX" usage="rp_blit"/> - <!-- Always written together and always equal 09510840 00000a62 --> - <reg32 offset="0x8120" name="GRAS_UNKNOWN_8120" variants="A7XX-" usage="cmd"/> - <reg32 offset="0x8121" name="GRAS_UNKNOWN_8121" variants="A7XX-" usage="cmd"/> + <doc>LUT used to convert quality buffer values to HW shading rate values. An array of 4-bit values.</doc> + <array offset="0x8120" name="GRAS_LRZ_QUALITY_LOOKUP_TABLE" variants="A7XX" stride="1" length="2"/> + <array offset="0x8130" name="GRAS_LRZ_QUALITY_LOOKUP_TABLE" variants="A8XX-" stride="1" length="2"/> - <!-- 0x8112-0x83ff invalid --> + <reg32 offset="0x810c" name="GRAS_LRZ_COLOR_COMP_MASK" variants="A8XX-"> + <bitfield name="MRT0" low="0" high="3"/> + <bitfield name="MRT1" low="4" high="7"/> + <bitfield name="MRT2" low="8" high="11"/> + <bitfield name="MRT3" low="12" high="15"/> + <bitfield name="MRT4" low="16" high="19"/> + <bitfield name="MRT5" low="20" high="23"/> + <bitfield name="MRT6" low="24" high="27"/> + <bitfield name="MRT7" low="28" high="31"/> + </reg32> <enum name="a6xx_rotation"> <value value="0x0" name="ROTATE_0"/> @@ -3430,7 +2109,7 @@ to upconvert to 32b float internally? <value value="0x5" name="ROTATE_VFLIP"/> </enum> - <bitset name="a6xx_2d_blit_cntl" inline="yes"> + <bitset name="a6xx_a2d_blt_cntl" inline="yes"> <bitfield name="ROTATE" low="0" high="2" type="a6xx_rotation"/> <bitfield name="OVERWRITEEN" pos="3" type="boolean"/> <bitfield name="UNK4" low="4" high="6"/> @@ -3442,67 +2121,72 @@ to upconvert to 32b float internally? <bitfield name="D24S8" pos="19" type="boolean"/> <!-- some sort of channel mask, disabled channels are set to zero ? --> <bitfield name="MASK" low="20" high="23"/> - <bitfield name="IFMT" low="24" high="28" type="a6xx_2d_ifmt"/> + <bitfield name="IFMT" low="24" high="26" type="a6xx_2d_ifmt"/> + <bitfield name="UNK27" pos="27" type="boolean"/> + <bitfield name="UNK28" pos="28" type="boolean"/> <bitfield name="RASTER_MODE" pos="29" type="a6xx_raster_mode"/> - <bitfield name="UNK30" pos="30" type="boolean" variants="A7XX-"/> + <bitfield name="COPY" pos="30" type="boolean" variants="A7XX-"/> </bitset> - <reg32 offset="0x8400" name="GRAS_2D_BLIT_CNTL" type="a6xx_2d_blit_cntl" usage="rp_blit"/> + <reg32 offset="0x8400" name="GRAS_A2D_BLT_CNTL" type="a6xx_a2d_blt_cntl" variants="A6XX-A7XX" usage="rp_blit"/> <!-- note: the low 8 bits for src coords are valid, probably fixed point it would be a bit weird though, since we subtract 1 from BR coords apparently signed, gallium driver uses negative coords and it works? --> - <reg32 offset="0x8401" name="GRAS_2D_SRC_TL_X" low="8" high="24" type="int" usage="rp_blit"/> - <reg32 offset="0x8402" name="GRAS_2D_SRC_BR_X" low="8" high="24" type="int" usage="rp_blit"/> - <reg32 offset="0x8403" name="GRAS_2D_SRC_TL_Y" low="8" high="24" type="int" usage="rp_blit"/> - <reg32 offset="0x8404" name="GRAS_2D_SRC_BR_Y" low="8" high="24" type="int" usage="rp_blit"/> - <reg32 offset="0x8405" name="GRAS_2D_DST_TL" type="a6xx_reg_xy" usage="rp_blit"/> - <reg32 offset="0x8406" name="GRAS_2D_DST_BR" type="a6xx_reg_xy" usage="rp_blit"/> + <reg32 offset="0x8401" name="GRAS_A2D_SRC_XMIN" low="8" high="24" type="int" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8402" name="GRAS_A2D_SRC_XMAX" low="8" high="24" type="int" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8403" name="GRAS_A2D_SRC_YMIN" low="8" high="24" type="int" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8404" name="GRAS_A2D_SRC_YMAX" low="8" high="24" type="int" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8405" name="GRAS_A2D_DEST_TL" type="a6xx_reg_xy" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x8406" name="GRAS_A2D_DEST_BR" type="a6xx_reg_xy" variants="A6XX-A7XX" usage="rp_blit"/> <reg32 offset="0x8407" name="GRAS_2D_UNKNOWN_8407" low="0" high="31"/> <reg32 offset="0x8408" name="GRAS_2D_UNKNOWN_8408" low="0" high="31"/> <reg32 offset="0x8409" name="GRAS_2D_UNKNOWN_8409" low="0" high="31"/> - <reg32 offset="0x840a" name="GRAS_2D_RESOLVE_CNTL_1" type="a6xx_reg_xy" usage="rp_blit"/> - <reg32 offset="0x840b" name="GRAS_2D_RESOLVE_CNTL_2" type="a6xx_reg_xy" usage="rp_blit"/> - <!-- 0x840c-0x85ff invalid --> + <reg32 offset="0x840a" name="GRAS_A2D_SCISSOR_TL" type="a6xx_reg_xy" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x840b" name="GRAS_A2D_SCISSOR_BR" type="a6xx_reg_xy" variants="A6XX-A7XX" usage="rp_blit"/> + + <reg32 offset="0x8500" name="GRAS_A2D_BLT_CNTL" type="a6xx_a2d_blt_cntl" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x8501" name="GRAS_A2D_SRC_XMIN" low="8" high="24" type="int" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x8502" name="GRAS_A2D_SRC_XMAX" low="8" high="24" type="int" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x8503" name="GRAS_A2D_SRC_YMIN" low="8" high="24" type="int" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x8504" name="GRAS_A2D_SRC_YMAX" low="8" high="24" type="int" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x8505" name="GRAS_A2D_DEST_TL" type="a6xx_reg_xy" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x8506" name="GRAS_A2D_DEST_BR" type="a6xx_reg_xy" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x8507" name="GRAS_A2D_SCISSOR_TL" type="a6xx_reg_xy" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x8508" name="GRAS_A2D_SCISSOR_BR" type="a6xx_reg_xy" variants="A8XX-" usage="rp_blit"/> <!-- always 0x880 ? (and 0 in a640/a650 traces?) --> - <reg32 offset="0x8600" name="GRAS_DBG_ECO_CNTL" usage="cmd"> + <reg32 offset="0x8600" name="GRAS_DBG_ECO_CNTL" usage="init" variants="A6XX-A7XX"> <bitfield name="UNK7" pos="7" type="boolean"/> <bitfield name="LRZCACHELOCKDIS" pos="11" type="boolean"/> </reg32> - <reg32 offset="0x8601" name="GRAS_ADDR_MODE_CNTL" pos="0" type="a5xx_address_mode"/> - <reg32 offset="0x8602" name="GRAS_NC_MODE_CNTL" variants="A7XX-"/> - <array offset="0x8610" name="GRAS_PERFCTR_TSE_SEL" stride="1" length="4"/> - <array offset="0x8614" name="GRAS_PERFCTR_RAS_SEL" stride="1" length="4"/> - <array offset="0x8618" name="GRAS_PERFCTR_LRZ_SEL" stride="1" length="4"/> + <reg32 offset="0x8600" name="GRAS_TSEFE_DBG_ECO_CNTL" variants="A8XX-"/> + <reg32 offset="0x8702" name="GRAS_DBG_ECO_CNTL" variants="A8XX"/> + <reg32 offset="0x8601" name="GRAS_ADDR_MODE_CNTL" pos="0" type="a5xx_address_mode" variants="A6XX"/> + <reg32 offset="0x8602" name="GRAS_NC_MODE_CNTL" variants="A7XX"/> + <reg32 offset="0x8700" name="GRAS_NC_MODE_CNTL" variants="A8XX-"/> + <array offset="0x8610" name="GRAS_PERFCTR_TSE_SEL" stride="1" length="4" variants="A6XX-A7XX"/> + <array offset="0x8614" name="GRAS_PERFCTR_RAS_SEL" stride="1" length="4" variants="A6XX-A7XX"/> + <array offset="0x8618" name="GRAS_PERFCTR_LRZ_SEL" stride="1" length="4" variants="A6XX-A7XX"/> + + <array offset="0x8610" name="GRAS_PERFCTR_TSEFE_SEL" stride="1" length="6" variants="A8XX-"/> + <array offset="0x8710" name="GRAS_PERFCTR_TSE_SEL" stride="1" length="6" variants="A8XX-"/> + <array offset="0x8720" name="GRAS_PERFCTR_RAS_SEL" stride="1" length="4" variants="A8XX-"/> + <array offset="0x8730" name="GRAS_PERFCTR_LRZ_SEL" stride="1" length="6" variants="A8XX-"/> + <!-- note 0x8620-0x87ff are not all invalid (in particular, 0x8631/0x8632 have 0x3fff3fff mask and would be xy coords) --> <!-- same as GRAS_BIN_CONTROL, but without bit 27: --> - <reg32 offset="0x8800" name="RB_BIN_CONTROL" variants="A6XX" usage="rp_blit"> - <bitfield name="BINW" low="0" high="5" shr="5" type="uint"/> - <bitfield name="BINH" low="8" high="14" shr="4" type="uint"/> - <bitfield name="RENDER_MODE" low="18" high="20" type="a6xx_render_mode"/> - <bitfield name="FORCE_LRZ_WRITE_DIS" pos="21" type="boolean"/> - <bitfield name="BUFFERS_LOCATION" low="22" high="23" type="a6xx_buffers_location"/> - <bitfield name="LRZ_FEEDBACK_ZMODE_MASK" low="24" high="26" type="a6xx_lrz_feedback_mask"/> - </reg32> - - <reg32 offset="0x8800" name="RB_BIN_CONTROL" variants="A7XX-" usage="rp_blit"> - <bitfield name="BINW" low="0" high="5" shr="5" type="uint"/> - <bitfield name="BINH" low="8" high="14" shr="4" type="uint"/> - <bitfield name="RENDER_MODE" low="18" high="20" type="a6xx_render_mode"/> - <bitfield name="FORCE_LRZ_WRITE_DIS" pos="21" type="boolean"/> - <bitfield name="LRZ_FEEDBACK_ZMODE_MASK" low="24" high="26" type="a6xx_lrz_feedback_mask"/> - </reg32> + <reg32 offset="0x8800" name="RB_CNTL" variants="A6XX-A7XX" type="a6xx_bin_cntl" usage="rp_blit"/> + <reg32 offset="0x8800" name="RB_CNTL" variants="A8XX-" type="a8xx_bin_cntl" usage="rp_blit"/> <reg32 offset="0x8801" name="RB_RENDER_CNTL" variants="A6XX" usage="rp_blit"> <bitfield name="CCUSINGLECACHELINESIZE" low="3" high="5"/> <bitfield name="EARLYVIZOUTEN" pos="6" type="boolean"/> - <!-- set during binning pass: --> - <bitfield name="BINNING" pos="7" type="boolean"/> + <bitfield name="FS_DISABLE" pos="7" type="boolean"/> <bitfield name="UNK8" low="8" high="10"/> <bitfield name="RASTER_MODE" pos="8" type="a6xx_raster_mode"/> <bitfield name="RASTER_DIRECTION" low="9" high="10" type="a6xx_raster_direction"/> @@ -3515,16 +2199,12 @@ to upconvert to 32b float internally? </reg32> <reg32 offset="0x8801" name="RB_RENDER_CNTL" variants="A7XX-" usage="rp_blit"> <bitfield name="EARLYVIZOUTEN" pos="6" type="boolean"/> - <!-- set during binning pass: --> - <bitfield name="BINNING" pos="7" type="boolean"/> + <bitfield name="FS_DISABLE" pos="7" type="boolean"/> <bitfield name="RASTER_MODE" pos="8" type="a6xx_raster_mode"/> <bitfield name="RASTER_DIRECTION" low="9" high="10" type="a6xx_raster_direction"/> <bitfield name="CONSERVATIVERASEN" pos="11" type="boolean"/> <bitfield name="INNERCONSERVATIVERASEN" pos="12" type="boolean"/> </reg32> - <reg32 offset="0x8116" name="GRAS_SU_RENDER_CNTL" variants="A7XX-" usage="rp_blit"> - <bitfield name="BINNING" pos="7" type="boolean"/> - </reg32> <reg32 offset="0x8802" name="RB_RAS_MSAA_CNTL" usage="rp_blit"> <bitfield name="SAMPLES" low="0" high="1" type="a3xx_msaa_samples"/> @@ -3536,16 +2216,17 @@ to upconvert to 32b float internally? <bitfield name="MSAA_DISABLE" pos="2" type="boolean"/> </reg32> - <reg32 offset="0x8804" name="RB_SAMPLE_CONFIG" type="a6xx_sample_config" usage="rp_blit"/> - <reg32 offset="0x8805" name="RB_SAMPLE_LOCATION_0" type="a6xx_sample_locations" usage="rp_blit"/> - <reg32 offset="0x8806" name="RB_SAMPLE_LOCATION_1" type="a6xx_sample_locations" usage="rp_blit"/> - <!-- 0x8807-0x8808 invalid --> + <reg32 offset="0x8804" name="RB_MSAA_SAMPLE_POS_CNTL" type="a6xx_msaa_sample_pos_cntl" usage="rp_blit"/> + <reg32 offset="0x8805" name="RB_PROGRAMMABLE_MSAA_POS_0" type="a6xx_programmable_msaa_pos" usage="rp_blit"/> + <reg32 offset="0x8806" name="RB_PROGRAMMABLE_MSAA_POS_1" type="a6xx_programmable_msaa_pos" usage="rp_blit"/> + <reg32 offset="0x8807" name="RB_PROGRAMMABLE_MSAA_POS_2" type="a6xx_programmable_msaa_pos" usage="rp_blit" variants="A8XX-"/> + <reg32 offset="0x8808" name="RB_PROGRAMMABLE_MSAA_POS_3" type="a6xx_programmable_msaa_pos" usage="rp_blit" variants="A8XX-"/> <!-- note: maybe not actually called RB_RENDER_CONTROLn (since RB_RENDER_CNTL name comes from kernel and is probably right) --> - <reg32 offset="0x8809" name="RB_RENDER_CONTROL0" usage="rp_blit"> - <!-- see also GRAS_CNTL --> + <reg32 offset="0x8809" name="RB_INTERP_CNTL" usage="rp_blit"> + <!-- see also GRAS_CL_INTERP_CNTL --> <bitfield name="IJ_PERSP_PIXEL" pos="0" type="boolean"/> <bitfield name="IJ_PERSP_CENTROID" pos="1" type="boolean"/> <bitfield name="IJ_PERSP_SAMPLE" pos="2" type="boolean"/> @@ -3553,9 +2234,9 @@ to upconvert to 32b float internally? <bitfield name="IJ_LINEAR_CENTROID" pos="4" type="boolean"/> <bitfield name="IJ_LINEAR_SAMPLE" pos="5" type="boolean"/> <bitfield name="COORD_MASK" low="6" high="9" type="hex"/> - <bitfield name="UNK10" pos="10" type="boolean"/> + <bitfield name="INTERP_EN" pos="10" type="boolean"/> </reg32> - <reg32 offset="0x880a" name="RB_RENDER_CONTROL1" usage="rp_blit"> + <reg32 offset="0x880a" name="RB_PS_INPUT_CNTL" usage="rp_blit"> <!-- enable bits for various FS sysvalue regs: --> <bitfield name="SAMPLEMASK" pos="0" type="boolean"/> <bitfield name="POSTDEPTHCOVERAGE" pos="1" type="boolean"/> @@ -3567,16 +2248,16 @@ to upconvert to 32b float internally? <bitfield name="FOVEATION" pos="8" type="boolean"/> </reg32> - <reg32 offset="0x880b" name="RB_FS_OUTPUT_CNTL0" usage="rp_blit"> + <reg32 offset="0x880b" name="RB_PS_OUTPUT_CNTL" usage="rp_blit"> <bitfield name="DUAL_COLOR_IN_ENABLE" pos="0" type="boolean"/> <bitfield name="FRAG_WRITES_Z" pos="1" type="boolean"/> <bitfield name="FRAG_WRITES_SAMPMASK" pos="2" type="boolean"/> <bitfield name="FRAG_WRITES_STENCILREF" pos="3" type="boolean"/> </reg32> - <reg32 offset="0x880c" name="RB_FS_OUTPUT_CNTL1" usage="rp_blit"> + <reg32 offset="0x880c" name="RB_PS_MRT_CNTL" usage="rp_blit"> <bitfield name="MRT" low="0" high="3" type="uint"/> </reg32> - <reg32 offset="0x880d" name="RB_RENDER_COMPONENTS" usage="rp_blit"> + <reg32 offset="0x880d" name="RB_PS_OUTPUT_MASK" usage="rp_blit"> <bitfield name="RT0" low="0" high="3"/> <bitfield name="RT1" low="4" high="7"/> <bitfield name="RT2" low="8" high="11"/> @@ -3608,11 +2289,35 @@ to upconvert to 32b float internally? <bitfield name="SRGB_MRT7" pos="7" type="boolean"/> </reg32> - <reg32 offset="0x8810" name="RB_SAMPLE_CNTL" usage="rp_blit"> + <reg32 offset="0x8810" name="RB_PS_SAMPLEFREQ_CNTL" usage="rp_blit"> <bitfield name="PER_SAMP_MODE" pos="0" type="boolean"/> </reg32> - <reg32 offset="0x8811" name="RB_UNKNOWN_8811" low="4" high="6" usage="cmd"/> - <reg32 offset="0x8812" name="RB_UNKNOWN_8812" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0x8811" name="RB_MODE_CNTL" low="4" high="6" usage="cmd"/> + <reg32 offset="0x8812" name="RB_BUFFER_CNTL" variants="A7XX-" usage="rp_blit"> + <bitfield name="Z_SYSMEM" pos="0" type="boolean"/> + <bitfield name="S_SYSMEM" pos="1" type="boolean"/> + <bitfield name="RT0_SYSMEM" pos="2" type="boolean"/> + <bitfield name="RT1_SYSMEM" pos="3" type="boolean"/> + <bitfield name="RT2_SYSMEM" pos="4" type="boolean"/> + <bitfield name="RT3_SYSMEM" pos="5" type="boolean"/> + <bitfield name="RT4_SYSMEM" pos="6" type="boolean"/> + <bitfield name="RT5_SYSMEM" pos="7" type="boolean"/> + <bitfield name="RT6_SYSMEM" pos="8" type="boolean"/> + <bitfield name="RT7_SYSMEM" pos="9" type="boolean"/> + <bitfield name="Z_FULL_IN_GMEM" pos="10" type="boolean" variants="A8XX-"/> + <bitfield name="S_FULL_IN_GMEM" pos="11" type="boolean" variants="A8XX-"/> + <bitfield name="RT0_FULL_IN_GMEM" pos="12" type="boolean" variants="A8XX-"/> + <bitfield name="RT1_FULL_IN_GMEM" pos="13" type="boolean" variants="A8XX-"/> + <bitfield name="RT2_FULL_IN_GMEM" pos="14" type="boolean" variants="A8XX-"/> + <bitfield name="RT3_FULL_IN_GMEM" pos="15" type="boolean" variants="A8XX-"/> + <bitfield name="RT4_FULL_IN_GMEM" pos="16" type="boolean" variants="A8XX-"/> + <bitfield name="RT5_FULL_IN_GMEM" pos="17" type="boolean" variants="A8XX-"/> + <bitfield name="RT6_FULL_IN_GMEM" pos="18" type="boolean" variants="A8XX-"/> + <bitfield name="RT7_FULL_IN_GMEM" pos="19" type="boolean" variants="A8XX-"/> + </reg32> + + <reg32 offset="0x8816" name="RB_RESOLVE_CR_CNTL" variants="A8XX-" usage="rp_blit"/> + <!-- 0x8813-0x8817 invalid --> <!-- always 0x0 ? --> <reg32 offset="0x8818" name="RB_UNKNOWN_8818" low="0" high="6" usage="cmd"/> @@ -3623,11 +2328,17 @@ to upconvert to 32b float internally? <reg32 offset="0x881c" name="RB_UNKNOWN_881C" usage="cmd"/> <reg32 offset="0x881d" name="RB_UNKNOWN_881D" usage="cmd"/> <reg32 offset="0x881e" name="RB_UNKNOWN_881E" usage="cmd"/> - <!-- 0x881f invalid --> + + <!-- Duplicates fields from SP_PS_CNTL_0 --> + <reg32 offset="0x881f" name="RB_PS_CNTL" variants="A8XX-" usage="rp_blit"> + <bitfield name="PIXLODENABLE" pos="0" type="boolean"/> + <bitfield name="LODPIXMASK" pos="1" type="boolean"/> + </reg32> + <array offset="0x8820" name="RB_MRT" stride="8" length="8" usage="rp_blit"> <reg32 offset="0x0" name="CONTROL"> - <bitfield name="BLEND" pos="0" type="boolean"/> - <bitfield name="BLEND2" pos="1" type="boolean"/> + <bitfield name="COLOR_BLEND_EN" pos="0" type="boolean"/> + <bitfield name="ALPHA_BLEND_EN" pos="1" type="boolean"/> <bitfield name="ROP_ENABLE" pos="2" type="boolean"/> <bitfield name="ROP_CODE" low="3" high="6" type="a3xx_rop_code"/> <bitfield name="COMPONENT_ENABLE" low="7" high="10" type="hex"/> @@ -3672,28 +2383,28 @@ to upconvert to 32b float internally? <reg32 offset="0x7" name="BASE_GMEM" low="12" high="31" shr="12"/> </array> - <reg32 offset="0x8860" name="RB_BLEND_RED_F32" type="float" usage="rp_blit"/> - <reg32 offset="0x8861" name="RB_BLEND_GREEN_F32" type="float" usage="rp_blit"/> - <reg32 offset="0x8862" name="RB_BLEND_BLUE_F32" type="float" usage="rp_blit"/> - <reg32 offset="0x8863" name="RB_BLEND_ALPHA_F32" type="float" usage="rp_blit"/> - <reg32 offset="0x8864" name="RB_ALPHA_CONTROL" usage="cmd"> + <reg32 offset="0x8860" name="RB_BLEND_CONSTANT_RED_FP32" type="float" usage="rp_blit"/> + <reg32 offset="0x8861" name="RB_BLEND_CONSTANT_GREEN_FP32" type="float" usage="rp_blit"/> + <reg32 offset="0x8862" name="RB_BLEND_CONSTANT_BLUE_FP32" type="float" usage="rp_blit"/> + <reg32 offset="0x8863" name="RB_BLEND_CONSTANT_ALPHA_FP32" type="float" usage="rp_blit"/> + <reg32 offset="0x8864" name="RB_ALPHA_TEST_CNTL" usage="cmd"> <bitfield name="ALPHA_REF" low="0" high="7" type="hex"/> <bitfield name="ALPHA_TEST" pos="8" type="boolean"/> <bitfield name="ALPHA_TEST_FUNC" low="9" high="11" type="adreno_compare_func"/> </reg32> <reg32 offset="0x8865" name="RB_BLEND_CNTL" usage="rp_blit"> <!-- per-mrt enable bit --> - <bitfield name="ENABLE_BLEND" low="0" high="7"/> + <bitfield name="BLEND_READS_DEST" low="0" high="7"/> <bitfield name="INDEPENDENT_BLEND" pos="8" type="boolean"/> <bitfield name="DUAL_COLOR_IN_ENABLE" pos="9" type="boolean"/> <bitfield name="ALPHA_TO_COVERAGE" pos="10" type="boolean"/> <bitfield name="ALPHA_TO_ONE" pos="11" type="boolean"/> <bitfield name="SAMPLE_MASK" low="16" high="31"/> </reg32> - <!-- 0x8866-0x886f invalid --> - <reg32 offset="0x8870" name="RB_DEPTH_PLANE_CNTL" usage="rp_blit"> - <bitfield name="Z_MODE" low="0" high="1" type="a6xx_ztest_mode"/> + <reg32 offset="0x8866" name="RB_LB_PARAM_LIMIT" variants="A8XX-" usage="rp_blit"> + <bitfield name="PRIMALLOCTHRESHOLD" low="0" high="2" type="uint"/> </reg32> + <reg32 offset="0x8870" name="RB_DEPTH_PLANE_CNTL" type="a6xx_depth_plane_cntl" usage="rp_blit"/> <reg32 offset="0x8871" name="RB_DEPTH_CNTL" usage="rp_blit"> <bitfield name="Z_TEST_ENABLE" pos="0" type="boolean"/> @@ -3706,19 +2417,15 @@ to upconvert to 32b float internally? </doc> <bitfield name="Z_READ_ENABLE" pos="6" type="boolean"/> <bitfield name="Z_BOUNDS_ENABLE" pos="7" type="boolean"/> + <!-- clamp shader depth out to [0, 1] (instead of RB_VIEWPORT_ZCLAMP_MIN/MAX)--> + <bitfield name="O_DEPTH_01_CLAMP_EN" pos="8" type="boolean" variants="A8XX-"/> </reg32> - <reg32 offset="0x8114" name="GRAS_SU_DEPTH_CNTL" usage="rp_blit"> - <bitfield name="Z_TEST_ENABLE" pos="0" type="boolean"/> - </reg32> + <!-- duplicates GRAS_SU_DEPTH_BUFFER_INFO: --> - <reg32 offset="0x8872" name="RB_DEPTH_BUFFER_INFO" variants="A6XX" usage="rp_blit"> - <bitfield name="DEPTH_FORMAT" low="0" high="2" type="a6xx_depth_format"/> - <bitfield name="UNK3" low="3" high="4"/> - </reg32> + <reg32 offset="0x8872" name="RB_DEPTH_BUFFER_INFO" variants="A6XX" type="a6xx_depth_buffer_info" usage="rp_blit"/> <!-- first 4 bits duplicates GRAS_SU_DEPTH_BUFFER_INFO --> - <reg32 offset="0x8872" name="RB_DEPTH_BUFFER_INFO" variants="A7XX-" usage="rp_blit"> - <bitfield name="DEPTH_FORMAT" low="0" high="2" type="a6xx_depth_format"/> - <bitfield name="UNK3" low="3" high="4"/> + <reg32 offset="0x8872" name="RB_DEPTH_BUFFER_INFO" type="a6xx_depth_buffer_info" variants="A7XX-" usage="rp_blit"> + <bitfield name="PRT" low="3" high="4"/> <bitfield name="TILEMODE" low="5" high="6" type="a6xx_tile_mode"/> <bitfield name="LOSSLESSCOMPEN" pos="7" type="boolean"/> </reg32> @@ -3726,12 +2433,12 @@ to upconvert to 32b float internally? <reg32 offset="0x8873" name="RB_DEPTH_BUFFER_PITCH" low="0" high="13" shr="6" type="uint" usage="rp_blit"/> <reg32 offset="0x8874" name="RB_DEPTH_BUFFER_ARRAY_PITCH" low="0" high="27" shr="6" type="uint" usage="rp_blit"/> <reg64 offset="0x8875" name="RB_DEPTH_BUFFER_BASE" type="waddress" align="64" usage="rp_blit"/> - <reg32 offset="0x8877" name="RB_DEPTH_BUFFER_BASE_GMEM" low="12" high="31" shr="12" usage="rp_blit"/> + <reg32 offset="0x8877" name="RB_DEPTH_GMEM_BASE" low="12" high="31" shr="12" usage="rp_blit"/> - <reg32 offset="0x8878" name="RB_Z_BOUNDS_MIN" type="float" usage="rp_blit"/> - <reg32 offset="0x8879" name="RB_Z_BOUNDS_MAX" type="float" usage="rp_blit"/> + <reg32 offset="0x8878" name="RB_DEPTH_BOUND_MIN" type="float" usage="rp_blit"/> + <reg32 offset="0x8879" name="RB_DEPTH_BOUND_MAX" type="float" usage="rp_blit"/> <!-- 0x887a-0x887f invalid --> - <reg32 offset="0x8880" name="RB_STENCIL_CONTROL" usage="rp_blit"> + <reg32 offset="0x8880" name="RB_STENCIL_CNTL" usage="rp_blit"> <bitfield name="STENCIL_ENABLE" pos="0" type="boolean"/> <bitfield name="STENCIL_ENABLE_BF" pos="1" type="boolean"/> <!-- @@ -3750,14 +2457,12 @@ to upconvert to 32b float internally? <bitfield name="ZPASS_BF" low="26" high="28" type="adreno_stencil_op"/> <bitfield name="ZFAIL_BF" low="29" high="31" type="adreno_stencil_op"/> </reg32> - <reg32 offset="0x8115" name="GRAS_SU_STENCIL_CNTL" usage="rp_blit"> - <bitfield name="STENCIL_ENABLE" pos="0" type="boolean"/> - </reg32> - <reg32 offset="0x8881" name="RB_STENCIL_INFO" variants="A6XX" usage="rp_blit"> + + <reg32 offset="0x8881" name="RB_STENCIL_BUFFER_INFO" variants="A6XX" usage="rp_blit"> <bitfield name="SEPARATE_STENCIL" pos="0" type="boolean"/> <bitfield name="UNK1" pos="1" type="boolean"/> </reg32> - <reg32 offset="0x8881" name="RB_STENCIL_INFO" variants="A7XX-" usage="rp_blit"> + <reg32 offset="0x8881" name="RB_STENCIL_BUFFER_INFO" variants="A7XX-" usage="rp_blit"> <bitfield name="SEPARATE_STENCIL" pos="0" type="boolean"/> <bitfield name="UNK1" pos="1" type="boolean"/> <bitfield name="TILEMODE" low="2" high="3" type="a6xx_tile_mode"/> @@ -3765,22 +2470,22 @@ to upconvert to 32b float internally? <reg32 offset="0x8882" name="RB_STENCIL_BUFFER_PITCH" low="0" high="11" shr="6" type="uint" usage="rp_blit"/> <reg32 offset="0x8883" name="RB_STENCIL_BUFFER_ARRAY_PITCH" low="0" high="23" shr="6" type="uint" usage="rp_blit"/> <reg64 offset="0x8884" name="RB_STENCIL_BUFFER_BASE" type="waddress" align="64" usage="rp_blit"/> - <reg32 offset="0x8886" name="RB_STENCIL_BUFFER_BASE_GMEM" low="12" high="31" shr="12" usage="rp_blit"/> - <reg32 offset="0x8887" name="RB_STENCILREF" usage="rp_blit"> + <reg32 offset="0x8886" name="RB_STENCIL_GMEM_BASE" low="12" high="31" shr="12" usage="rp_blit"/> + <reg32 offset="0x8887" name="RB_STENCIL_REF_CNTL" usage="rp_blit"> <bitfield name="REF" low="0" high="7"/> <bitfield name="BFREF" low="8" high="15"/> </reg32> - <reg32 offset="0x8888" name="RB_STENCILMASK" usage="rp_blit"> + <reg32 offset="0x8888" name="RB_STENCIL_MASK" usage="rp_blit"> <bitfield name="MASK" low="0" high="7"/> <bitfield name="BFMASK" low="8" high="15"/> </reg32> - <reg32 offset="0x8889" name="RB_STENCILWRMASK" usage="rp_blit"> + <reg32 offset="0x8889" name="RB_STENCIL_WRITE_MASK" usage="rp_blit"> <bitfield name="WRMASK" low="0" high="7"/> <bitfield name="BFWRMASK" low="8" high="15"/> </reg32> <!-- 0x888a-0x888f invalid --> <reg32 offset="0x8890" name="RB_WINDOW_OFFSET" type="a6xx_reg_xy" usage="rp_blit"/> - <reg32 offset="0x8891" name="RB_SAMPLE_COUNT_CONTROL" usage="cmd"> + <reg32 offset="0x8891" name="RB_SAMPLE_COUNTER_CNTL" usage="cmd"> <bitfield name="DISABLE" pos="0" type="boolean"/> <bitfield name="COPY" pos="1" type="boolean"/> </reg32> @@ -3788,30 +2493,46 @@ to upconvert to 32b float internally? <reg32 offset="0x8898" name="RB_LRZ_CNTL" usage="rp_blit"> <bitfield name="ENABLE" pos="0" type="boolean"/> </reg32> - <reg32 offset="0x8899" name="RB_UNKNOWN_8899" variants="A7XX-" usage="cmd"/> + <reg32 offset="0x8899" name="RB_LRZ_CNTL2" variants="A7XX-" usage="cmd"> + <bitfield name="ENABLE_BIDIRECTIONAL_LRZ" pos="0" type="boolean"/> + </reg32> <!-- 0x8899-0x88bf invalid --> <!-- clamps depth value for depth test/write --> - <reg32 offset="0x88c0" name="RB_Z_CLAMP_MIN" type="float" usage="rp_blit"/> - <reg32 offset="0x88c1" name="RB_Z_CLAMP_MAX" type="float" usage="rp_blit"/> + <reg32 offset="0x88c0" name="RB_VIEWPORT_ZCLAMP_MIN" type="float" usage="rp_blit" variants="A6XX-A7XX"/> + <reg32 offset="0x88c1" name="RB_VIEWPORT_ZCLAMP_MAX" type="float" usage="rp_blit" variants="A6XX-A7XX"/> + +<!-- todo allow type="float" on an <array/> --> + <array offset="0x88b0" name="RB_VIEWPORT_ZCLAMP_MIN" stride="1" length="16" usage="rp_blit" variants="A8XX-"> + <reg32 offset="0" name="REG" type="float"/> + </array> + <array offset="0x88c0" name="RB_VIEWPORT_ZCLAMP_MAX" stride="1" length="16" usage="rp_blit" variants="A8XX-"> + <reg32 offset="0" name="REG" type="float"/> + </array> + <!-- 0x88c2-0x88cf invalid--> - <reg32 offset="0x88d0" name="RB_UNKNOWN_88D0" usage="rp_blit"> + <reg32 offset="0x88d0" name="RB_RESOLVE_CNTL_0" usage="rp_blit"> <bitfield name="UNK0" low="0" high="12"/> <bitfield name="UNK16" low="16" high="26"/> </reg32> - <reg32 offset="0x88d1" name="RB_BLIT_SCISSOR_TL" type="a6xx_reg_xy" usage="rp_blit"/> - <reg32 offset="0x88d2" name="RB_BLIT_SCISSOR_BR" type="a6xx_reg_xy" usage="rp_blit"/> + <reg32 offset="0x88d1" name="RB_RESOLVE_CNTL_1" type="a6xx_reg_xy" usage="rp_blit"/> + <reg32 offset="0x88d2" name="RB_RESOLVE_CNTL_2" type="a6xx_reg_xy" usage="rp_blit"/> <!-- weird to duplicate other regs from same block?? --> - <reg32 offset="0x88d3" name="RB_BIN_CONTROL2" usage="rp_blit"> + <reg32 offset="0x88d3" name="RB_RESOLVE_CNTL_3" variants="A6XX-A7XX" usage="rp_blit"> <bitfield name="BINW" low="0" high="5" shr="5" type="uint"/> <bitfield name="BINH" low="8" high="14" shr="4" type="uint"/> </reg32> - <reg32 offset="0x88d4" name="RB_WINDOW_OFFSET2" type="a6xx_reg_xy" usage="rp_blit"/> - <reg32 offset="0x88d5" name="RB_BLIT_GMEM_MSAA_CNTL" usage="rp_blit"> + + <reg32 offset="0x88d3" name="RB_RESOLVE_CNTL_3" type="a8xx_bin_size" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x88f0" name="RB_RESOLVE_CNTL_4" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x88f1" name="RB_RESOLVE_CNTL_5" variants="A8XX-" usage="rp_blit"/> + + <reg32 offset="0x88d4" name="RB_RESOLVE_WINDOW_OFFSET" type="a6xx_reg_xy" usage="rp_blit"/> + <reg32 offset="0x88d5" name="RB_RESOLVE_GMEM_BUFFER_INFO" usage="rp_blit"> <bitfield name="SAMPLES" low="3" high="4" type="a3xx_msaa_samples"/> </reg32> - <reg32 offset="0x88d6" name="RB_BLIT_BASE_GMEM" low="12" high="31" shr="12" usage="rp_blit"/> + <reg32 offset="0x88d6" name="RB_RESOLVE_GMEM_BUFFER_BASE" low="12" high="31" shr="12" usage="rp_blit"/> <!-- s/DST_FORMAT/DST_INFO/ probably: --> - <reg32 offset="0x88d7" name="RB_BLIT_DST_INFO" usage="rp_blit"> + <reg32 offset="0x88d7" name="RB_RESOLVE_SYSTEM_BUFFER_INFO" usage="rp_blit"> <bitfield name="TILE_MODE" low="0" high="1" type="a6xx_tile_mode"/> <bitfield name="FLAGS" pos="2" type="boolean"/> <bitfield name="SAMPLES" low="3" high="4" type="a3xx_msaa_samples"/> @@ -3820,25 +2541,34 @@ to upconvert to 32b float internally? <bitfield name="UNK15" pos="15" type="boolean"/> <bitfield name="MUTABLEEN" pos="16" type="boolean" variants="A7XX-"/> </reg32> - <reg64 offset="0x88d8" name="RB_BLIT_DST" type="waddress" align="64" usage="rp_blit"/> - <reg32 offset="0x88da" name="RB_BLIT_DST_PITCH" low="0" high="15" shr="6" type="uint" usage="rp_blit"/> + <reg64 offset="0x88d8" name="RB_RESOLVE_SYSTEM_BUFFER_BASE" type="waddress" align="64" usage="rp_blit"/> + <reg32 offset="0x88da" name="RB_RESOLVE_SYSTEM_BUFFER_PITCH" low="0" high="15" shr="6" type="uint" usage="rp_blit"/> <!-- array-pitch is size of layer --> - <reg32 offset="0x88db" name="RB_BLIT_DST_ARRAY_PITCH" low="0" high="28" shr="6" type="uint" usage="rp_blit"/> - <reg64 offset="0x88dc" name="RB_BLIT_FLAG_DST" type="waddress" align="64" usage="rp_blit"/> - <reg32 offset="0x88de" name="RB_BLIT_FLAG_DST_PITCH" usage="rp_blit"> + <reg32 offset="0x88db" name="RB_RESOLVE_SYSTEM_BUFFER_ARRAY_PITCH" low="0" high="28" shr="6" type="uint" usage="rp_blit"/> + <reg64 offset="0x88dc" name="RB_RESOLVE_SYSTEM_FLAG_BUFFER_BASE" type="waddress" align="64" usage="rp_blit"/> + + <bitset name="a6xx_flag_buffer_pitch" inline="yes"> <bitfield name="PITCH" low="0" high="10" shr="6" type="uint"/> - <bitfield name="ARRAY_PITCH" low="11" high="27" shr="7" type="uint"/> - </reg32> + <bitfield name="ARRAY_PITCH" low="11" high="28" shr="7" type="uint"/> + </bitset> + + <reg32 offset="0x88de" name="RB_RESOLVE_SYSTEM_FLAG_BUFFER_PITCH" type="a6xx_flag_buffer_pitch" usage="rp_blit"/> - <reg32 offset="0x88df" name="RB_BLIT_CLEAR_COLOR_DW0" usage="rp_blit"/> - <reg32 offset="0x88e0" name="RB_BLIT_CLEAR_COLOR_DW1" usage="rp_blit"/> - <reg32 offset="0x88e1" name="RB_BLIT_CLEAR_COLOR_DW2" usage="rp_blit"/> - <reg32 offset="0x88e2" name="RB_BLIT_CLEAR_COLOR_DW3" usage="rp_blit"/> + <reg32 offset="0x88df" name="RB_RESOLVE_CLEAR_COLOR_DW0" usage="rp_blit"/> + <reg32 offset="0x88e0" name="RB_RESOLVE_CLEAR_COLOR_DW1" usage="rp_blit"/> + <reg32 offset="0x88e1" name="RB_RESOLVE_CLEAR_COLOR_DW2" usage="rp_blit"/> + <reg32 offset="0x88e2" name="RB_RESOLVE_CLEAR_COLOR_DW3" usage="rp_blit"/> + + <enum name="a6xx_blit_event_type"> + <value value="0x0" name="BLIT_EVENT_STORE"/> + <value value="0x1" name="BLIT_EVENT_STORE_AND_CLEAR"/> + <value value="0x2" name="BLIT_EVENT_CLEAR"/> + <value value="0x3" name="BLIT_EVENT_LOAD"/> + </enum> <!-- seems somewhat similar to what we called RB_CLEAR_CNTL on a5xx: --> - <reg32 offset="0x88e3" name="RB_BLIT_INFO" usage="rp_blit"> - <bitfield name="UNK0" pos="0" type="boolean"/> <!-- s8 stencil restore/clear? But also color restore? --> - <bitfield name="GMEM" pos="1" type="boolean"/> <!-- set for restore and clear to gmem? --> + <reg32 offset="0x88e3" name="RB_RESOLVE_OPERATION" usage="rp_blit"> + <bitfield name="TYPE" low="0" high="1" type="a6xx_blit_event_type"/> <bitfield name="SAMPLE_0" pos="2" type="boolean"/> <!-- takes sample 0 instead of averaging --> <bitfield name="DEPTH" pos="3" type="boolean"/> <!-- z16/z32/z24s8/x24x8 clear or resolve? --> <doc> @@ -3853,16 +2583,20 @@ to upconvert to 32b float internally? <!-- set when this is the last resolve on a650+ --> <bitfield name="LAST" low="8" high="9"/> <!-- - a618 GLES: color render target number being resolved for RM6_RESOLVE, 0x8 for depth, 0x9 for separate stencil. - a618 VK: 0x8 for depth RM6_RESOLVE, 0x9 for separate stencil, 0 otherwise. - - We believe this is related to concurrent resolves + a618 GLES: color render target number being resolved for CCU_RESOLVE, 0x8 for depth, 0x9 for separate stencil. + a618 VK: 0x8 for depth CCU_RESOLVE, 0x9 for separate stencil, 0 otherwise. + a7xx VK: 0x8 for depth, 0x9 for separate stencil, 0x0 to 0x7 used for concurrent resolves of color render + targets inside a given resolve group. --> <bitfield name="BUFFER_ID" low="12" high="15"/> </reg32> - <reg32 offset="0x88e4" name="RB_UNKNOWN_88E4" variants="A7XX-" usage="rp_blit"> - <!-- Value conditioned based on predicate, changed before blits --> - <bitfield name="UNK0" pos="0" type="boolean"/> + + <enum name="a7xx_blit_clear_mode"> + <value value="0x0" name="CLEAR_MODE_SYSMEM"/> + <value value="0x1" name="CLEAR_MODE_GMEM"/> + </enum> + <reg32 offset="0x88e4" name="RB_CLEAR_TARGET" variants="A7XX-" usage="rp_blit"> + <bitfield name="CLEAR_MODE" pos="0" type="a7xx_blit_clear_mode"/> </reg32> <enum name="a6xx_ccu_cache_size"> @@ -3870,8 +2604,10 @@ to upconvert to 32b float internally? <value value="0x1" name="CCU_CACHE_SIZE_HALF"/> <value value="0x2" name="CCU_CACHE_SIZE_QUARTER"/> <value value="0x3" name="CCU_CACHE_SIZE_EIGHTH"/> + <!-- for DEPTH_CACHE_SIZE 3 == THREE_QUARTER from KNP --> + <value value="0x3" name="CCU_CACHE_SIZE_THREE_QUARTER"/> </enum> - <reg32 offset="0x88e5" name="RB_CCU_CNTL2" variants="A7XX-" usage="cmd"> + <reg32 offset="0x88e5" name="RB_CCU_CACHE_CNTL" variants="A7XX" usage="cmd"> <bitfield name="DEPTH_OFFSET_HI" pos="0" type="hex"/> <bitfield name="COLOR_OFFSET_HI" pos="2" type="hex"/> <bitfield name="DEPTH_CACHE_SIZE" low="10" high="11" type="a6xx_ccu_cache_size"/> @@ -3886,18 +2622,40 @@ to upconvert to 32b float internally? --> <bitfield name="COLOR_OFFSET" low="23" high="31" shr="12" type="hex"/> </reg32> - <!-- 0x88e6-0x88ef invalid --> + + <reg32 offset="0x88e5" name="RB_CCU_CACHE_CNTL" variants="A8XX-" usage="cmd"> + <!-- + For color cache, full is 128KB per CCU. For depth cache, + full is 256KB per CCU. + + For attr/pos caches (see VPC_{ATTR,POS,BV_POS}_BUF_GMEM_SIZE), + the sizes are per CCU + --> + <bitfield name="COLOR_OFFSET" low="0" high="13" shr="12" type="hex"/> + <bitfield name="COLOR_CACHE_SIZE" low="14" high="15" type="a6xx_ccu_cache_size"/> + <bitfield name="DEPTH_OFFSET" low="16" high="29" shr="12" type="hex"/> + <bitfield name="DEPTH_CACHE_SIZE" low="30" high="31" type="a6xx_ccu_cache_size"/> + </reg32> + + <reg32 offset="0x88e6" name="RB_RESOLVE_GMEM_BUFFER_CNTL" variants="A8XX-"> + <bitfield name="FULL_IN_GMEM" pos="0" type="boolean"/> + </reg32> + <!-- always 0x0 ? --> - <reg32 offset="0x88f0" name="RB_UNKNOWN_88F0" low="0" high="11" usage="cmd"/> + <reg32 offset="0x88f0" name="RB_UNKNOWN_88F0" low="0" high="11" variants="A6XX" usage="cmd"/> <!-- could be for separate stencil? (or may not be a flag buffer at all) --> - <reg64 offset="0x88f1" name="RB_UNK_FLAG_BUFFER_BASE" type="waddress" align="64"/> - <reg32 offset="0x88f3" name="RB_UNK_FLAG_BUFFER_PITCH"> - <bitfield name="PITCH" low="0" high="10" shr="6" type="uint"/> - <bitfield name="ARRAY_PITCH" low="11" high="23" shr="7" type="uint"/> + <reg64 offset="0x88f1" name="RB_UNK_FLAG_BUFFER_BASE" type="waddress" align="64" variants="A6XX"/> + <reg32 offset="0x88f3" name="RB_UNK_FLAG_BUFFER_PITCH" type="a6xx_flag_buffer_pitch" variants="A6XX"/> + + <reg32 offset="0x88f4" name="RB_VRS_CONFIG" usage="rp_blit"> + <bitfield name="UNK2" pos="2" type="boolean"/> + <bitfield name="PIPELINE_FSR_ENABLE" pos="4" type="boolean"/> + <bitfield name="ATTACHMENT_FSR_ENABLE" pos="5" type="boolean"/> + <bitfield name="PRIMITIVE_FSR_ENABLE" pos="18" type="boolean"/> + </reg32> + <reg32 offset="0x88f5" name="RB_BIN_FOVEAT" variants="A7XX-" usage="cmd"> + <bitfield name="BINSCALEEN" pos="6" type="boolean"/> </reg32> - <reg32 offset="0x88f4" name="RB_UNKNOWN_88F4" low="0" high="2"/> - <!-- Connected to VK_EXT_fragment_density_map? --> - <reg32 offset="0x88f5" name="RB_UNKNOWN_88F5" variants="A7XX-"/> <!-- 0x88f6-0x88ff invalid --> <reg64 offset="0x8900" name="RB_DEPTH_FLAG_BUFFER_BASE" type="waddress" align="64" usage="rp_blit"/> <reg32 offset="0x8902" name="RB_DEPTH_FLAG_BUFFER_PITCH" usage="rp_blit"> @@ -3906,22 +2664,30 @@ to upconvert to 32b float internally? <bitfield name="UNK8" low="8" high="10"/> <bitfield name="ARRAY_PITCH" low="11" high="27" shr="7" type="uint"/> </reg32> - <array offset="0x8903" name="RB_MRT_FLAG_BUFFER" stride="3" length="8" usage="rp_blit"> + + <array offset="0x8903" name="RB_COLOR_FLAG_BUFFER" stride="3" length="8" usage="rp_blit"> <reg64 offset="0" name="ADDR" type="waddress" align="64"/> - <reg32 offset="2" name="PITCH"> - <bitfield name="PITCH" low="0" high="10" shr="6" type="uint"/> - <bitfield name="ARRAY_PITCH" low="11" high="28" shr="7" type="uint"/> - </reg32> + <reg32 offset="2" name="PITCH" type="a6xx_flag_buffer_pitch"/> </array> <!-- 0x891b-0x8926 invalid --> <doc> - RB_SAMPLE_COUNT_ADDR register is used up to (and including) a730. After that + RB_SAMPLE_COUNTER_BASE register is used up to (and including) a730. After that the address is specified through CP_EVENT_WRITE7::WRITE_SAMPLE_COUNT. </doc> - <reg64 offset="0x8927" name="RB_SAMPLE_COUNT_ADDR" type="waddress" align="16" usage="cmd"/> - <!-- 0x8929-0x89ff invalid --> + <reg64 offset="0x8927" name="RB_SAMPLE_COUNTER_BASE" type="waddress" align="16" usage="cmd"/> - <!-- TODO: there are some registers in the 0x8a00-0x8bff range --> + <bitset name="a8xx_gmem_dimension" inline="yes"> + <bitfield name="WIDTH" low="0" high="14" type="uint"/> + <bitfield name="HEIGHT" low="16" high="30" type="uint"/> + </bitset> + + <reg32 offset="0x8813" name="RB_DEPTH_GMEM_DIMENSION" type="a8xx_gmem_dimension" variants="A8XX-"/> + <reg32 offset="0x8814" name="RB_STENCIL_GMEM_DIMENSION" type="a8xx_gmem_dimension" variants="A8XX-"/> + <reg32 offset="0x8815" name="RB_RESOLVE_GMEM_DIMENSION" type="a8xx_gmem_dimension" variants="A8XX-"/> + + <array offset="0x8930" name="RB_MRT_GMEM_DIMENSION" variants="A8XX-" stride="1" length="8"> + <reg32 offset="0" name="REG" type="a8xx_gmem_dimension"/> + </array> <!-- These show up in a6xx gen3+ but so far haven't found an example of @@ -3932,10 +2698,10 @@ to upconvert to 32b float internally? <reg32 offset="0x8a20" name="RB_UNKNOWN_8A20" variants="A6XX" usage="rp_blit"/> <reg32 offset="0x8a30" name="RB_UNKNOWN_8A30" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0x8c00" name="RB_2D_BLIT_CNTL" type="a6xx_2d_blit_cntl" usage="rp_blit"/> - <reg32 offset="0x8c01" name="RB_2D_UNKNOWN_8C01" low="0" high="31" usage="rp_blit"/> + <reg32 offset="0x8c00" name="RB_A2D_BLT_CNTL" type="a6xx_a2d_blt_cntl" usage="rp_blit"/> + <reg32 offset="0x8c01" name="RB_A2D_PIXEL_CNTL" low="0" high="31" usage="rp_blit"/> - <bitset name="a6xx_2d_src_surf_info" inline="yes"> + <bitset name="a6xx_a2d_src_texture_info" inline="yes"> <bitfield name="COLOR_FORMAT" low="0" high="7" type="a6xx_format"/> <bitfield name="TILE_MODE" low="8" high="9" type="a6xx_tile_mode"/> <bitfield name="COLOR_SWAP" low="10" high="11" type="a3xx_color_swap"/> @@ -3954,7 +2720,7 @@ to upconvert to 32b float internally? <bitfield name="MUTABLEEN" pos="29" type="boolean" variants="A7XX-"/> </bitset> - <bitset name="a6xx_2d_dst_surf_info" inline="yes"> + <bitset name="a6xx_a2d_dest_buffer_info" inline="yes"> <bitfield name="COLOR_FORMAT" low="0" high="7" type="a6xx_format"/> <bitfield name="TILE_MODE" low="8" high="9" type="a6xx_tile_mode"/> <bitfield name="COLOR_SWAP" low="10" high="11" type="a3xx_color_swap"/> @@ -3965,38 +2731,38 @@ to upconvert to 32b float internally? </bitset> <!-- 0x8c02-0x8c16 invalid --> - <reg32 offset="0x8c17" name="RB_2D_DST_INFO" type="a6xx_2d_dst_surf_info" usage="rp_blit"/> - <reg64 offset="0x8c18" name="RB_2D_DST" type="waddress" align="64" usage="rp_blit"/> - <reg32 offset="0x8c1a" name="RB_2D_DST_PITCH" low="0" high="15" shr="6" type="uint" usage="rp_blit"/> + <reg32 offset="0x8c17" name="RB_A2D_DEST_BUFFER_INFO" type="a6xx_a2d_dest_buffer_info" usage="rp_blit"/> + <reg64 offset="0x8c18" name="RB_A2D_DEST_BUFFER_BASE" type="waddress" align="64" usage="rp_blit"/> + <reg32 offset="0x8c1a" name="RB_A2D_DEST_BUFFER_PITCH" low="0" high="15" shr="6" type="uint" usage="rp_blit"/> <!-- this is a guess but seems likely (for NV12/IYUV): --> - <reg64 offset="0x8c1b" name="RB_2D_DST_PLANE1" type="waddress" align="64" usage="rp_blit"/> - <reg32 offset="0x8c1d" name="RB_2D_DST_PLANE_PITCH" low="0" high="15" shr="6" type="uint" usage="rp_blit"/> - <reg64 offset="0x8c1e" name="RB_2D_DST_PLANE2" type="waddress" align="64" usage="rp_blit"/> + <reg64 offset="0x8c1b" name="RB_A2D_DEST_BUFFER_BASE_1" type="waddress" align="64" usage="rp_blit"/> + <reg32 offset="0x8c1d" name="RB_A2D_DEST_BUFFER_PITCH_1" low="0" high="15" shr="6" type="uint" usage="rp_blit"/> + <reg64 offset="0x8c1e" name="RB_A2D_DEST_BUFFER_BASE_2" type="waddress" align="64" usage="rp_blit"/> - <reg64 offset="0x8c20" name="RB_2D_DST_FLAGS" type="waddress" align="64" usage="rp_blit"/> - <reg32 offset="0x8c22" name="RB_2D_DST_FLAGS_PITCH" low="0" high="7" shr="6" type="uint" usage="rp_blit"/> + <reg64 offset="0x8c20" name="RB_A2D_DEST_FLAG_BUFFER_BASE" type="waddress" align="64" usage="rp_blit"/> + <reg32 offset="0x8c22" name="RB_A2D_DEST_FLAG_BUFFER_PITCH" type="a6xx_flag_buffer_pitch" usage="rp_blit"/> <!-- this is a guess but seems likely (for NV12 with UBWC): --> - <reg64 offset="0x8c23" name="RB_2D_DST_FLAGS_PLANE" type="waddress" align="64" usage="rp_blit"/> - <reg32 offset="0x8c25" name="RB_2D_DST_FLAGS_PLANE_PITCH" low="0" high="7" shr="6" type="uint" usage="rp_blit"/> + <reg64 offset="0x8c23" name="RB_A2D_DEST_FLAG_BUFFER_BASE_1" type="waddress" align="64" usage="rp_blit"/> + <reg32 offset="0x8c25" name="RB_A2D_DEST_FLAG_BUFFER_PITCH_1" low="0" high="7" shr="6" type="uint" usage="rp_blit"/> <!-- TODO: 0x8c26-0x8c33 are all full 32-bit registers --> <!-- unlike a5xx, these are per channel values rather than packed --> - <reg32 offset="0x8c2c" name="RB_2D_SRC_SOLID_C0" usage="rp_blit"/> - <reg32 offset="0x8c2d" name="RB_2D_SRC_SOLID_C1" usage="rp_blit"/> - <reg32 offset="0x8c2e" name="RB_2D_SRC_SOLID_C2" usage="rp_blit"/> - <reg32 offset="0x8c2f" name="RB_2D_SRC_SOLID_C3" usage="rp_blit"/> + <reg32 offset="0x8c2c" name="RB_A2D_CLEAR_COLOR_DW0" usage="rp_blit"/> + <reg32 offset="0x8c2d" name="RB_A2D_CLEAR_COLOR_DW1" usage="rp_blit"/> + <reg32 offset="0x8c2e" name="RB_A2D_CLEAR_COLOR_DW2" usage="rp_blit"/> + <reg32 offset="0x8c2f" name="RB_A2D_CLEAR_COLOR_DW3" usage="rp_blit"/> <reg32 offset="0x8c34" name="RB_UNKNOWN_8C34" variants="A7XX-" usage="cmd"/> <!-- 0x8c35-0x8dff invalid --> <!-- always 0x1 ? either doesn't exist for a650 or write-only: --> - <reg32 offset="0x8e01" name="RB_UNKNOWN_8E01" usage="cmd"/> + <reg32 offset="0x8e01" name="RB_RBP_CNTL" usage="cmd"/> <!-- 0x8e00-0x8e03 invalid --> <reg32 offset="0x8e04" name="RB_DBG_ECO_CNTL" usage="cmd"/> <!-- TODO: valid mask 0xfffffeff --> - <reg32 offset="0x8e05" name="RB_ADDR_MODE_CNTL" pos="0" type="a5xx_address_mode"/> + <reg32 offset="0x8e05" name="RB_ADDR_MODE_CNTL" pos="0" type="a5xx_address_mode" variants="A6XX"/> <!-- 0x02080000 in GMEM, zero otherwise? --> - <reg32 offset="0x8e06" name="RB_UNKNOWN_8E06" variants="A7XX-" usage="cmd"/> + <reg32 offset="0x8e06" name="RB_CCU_DBG_ECO_CNTL" variants="A7XX-" usage="cmd"/> <reg32 offset="0x8e07" name="RB_CCU_CNTL" usage="cmd" variants="A6XX"> <bitfield name="GMEM_FAST_CLEAR_DISABLE" pos="0" type="boolean"/> @@ -4017,12 +2783,23 @@ to upconvert to 32b float internally? <bitfield name="COLOR_OFFSET" low="23" high="31" shr="12" type="hex"/> <!--TODO: valid mask 0xfffffc1f --> </reg32> + <enum name="a7xx_concurrent_resolve_mode"> + <value value="0x0" name="CONCURRENT_RESOLVE_MODE_DISABLED"/> + <value value="0x1" name="CONCURRENT_RESOLVE_MODE_1"/> + <value value="0x2" name="CONCURRENT_RESOLVE_MODE_2"/> + </enum> + <enum name="a7xx_concurrent_unresolve_mode"> + <value value="0x0" name="CONCURRENT_UNRESOLVE_MODE_DISABLED"/> + <value value="0x1" name="CONCURRENT_UNRESOLVE_MODE_PARTIAL"/> + <value value="0x3" name="CONCURRENT_UNRESOLVE_MODE_FULL"/> + </enum> <reg32 offset="0x8e07" name="RB_CCU_CNTL" usage="cmd" variants="A7XX-"> <bitfield name="GMEM_FAST_CLEAR_DISABLE" pos="0" type="boolean"/> - <bitfield name="CONCURRENT_RESOLVE" pos="2" type="boolean"/> - <!-- rest of the bits were moved to RB_CCU_CNTL2 --> + <bitfield name="CONCURRENT_RESOLVE_MODE" low="2" high="3" type="a7xx_concurrent_resolve_mode"/> + <bitfield name="CONCURRENT_UNRESOLVE_MODE" low="5" high="6" type="a7xx_concurrent_unresolve_mode"/> + <!-- rest of the bits were moved to RB_CCU_CACHE_CNTL --> </reg32> - <reg32 offset="0x8e08" name="RB_NC_MODE_CNTL"> + <reg32 offset="0x8e08" name="RB_NC_MODE_CNTL" variants="A6XX-A7XX"> <bitfield name="MODE" pos="0" type="boolean"/> <bitfield name="LOWER_BIT" low="1" high="2" type="uint"/> <bitfield name="MIN_ACCESS_LENGTH" pos="3" type="boolean"/> <!-- true=64b false=32b --> @@ -4031,26 +2808,40 @@ to upconvert to 32b float internally? <bitfield name="RGB565_PREDICATOR" pos="11" type="boolean"/> <bitfield name="UNK12" low="12" high="13"/> </reg32> - <reg32 offset="0x8e09" name="RB_UNKNOWN_8E09" variants="A7XX-" usage="cmd"/> + <reg32 offset="0x8e08" name="RB_CCU_NC_MODE_CNTL" variants="A8XX-"/> + + <reg32 offset="0x8e09" name="RB_UNKNOWN_8E09" variants="A7XX" usage="cmd"/> + <reg32 offset="0x8e09" name="RB_GC_GMEM_PROTECT" variants="A8XX-"/> + <reg32 offset="0x8e0a" name="RB_LPAC_GMEM_PROTECT" variants="A8XX-"/> <!-- 0x8e09-0x8e0f invalid --> <array offset="0x8e10" name="RB_PERFCTR_RB_SEL" stride="1" length="8"/> <array offset="0x8e18" name="RB_PERFCTR_CCU_SEL" stride="1" length="5"/> <!-- 0x8e1d-0x8e1f invalid --> <!-- 0x8e20-0x8e25 more perfcntr sel? --> <!-- 0x8e26-0x8e27 invalid --> - <reg32 offset="0x8e28" name="RB_CMP_DBG_ECO_CNTL"/> + + <reg32 offset="0x8f00" name="RB_CMP_NC_MODE_CNTL" variants="A8XX-"/> + <reg32 offset="0x8f01" name="RB_RESOLVE_PREFETCH_CNTL" variants="A8XX-"/> + <reg32 offset="0x8f02" name="RB_CMP_DBG_ECO_CNTL" variants="A8XX-"/> + + <reg32 offset="0x8f03" name="RB_UNSLICE_STATUS" variants="A8XX-"/> + <reg32 offset="0x8e28" name="RB_CMP_DBG_ECO_CNTL" variants="A6XX-A7XX"/> <!-- 0x8e29-0x8e2b invalid --> - <array offset="0x8e2c" name="RB_PERFCTR_CMP_SEL" stride="1" length="4"/> - <array offset="0x8e30" name="RB_PERFCTR_UFC_SEL" stride="1" length="6" variants="A7XX-"/> - <reg32 offset="0x8e3b" name="RB_RB_SUB_BLOCK_SEL_CNTL_HOST"/> - <reg32 offset="0x8e3d" name="RB_RB_SUB_BLOCK_SEL_CNTL_CD"/> + <array offset="0x8e2c" name="RB_PERFCTR_CMP_SEL" stride="1" length="4" variants="A6XX-A7XX"/> + <array offset="0x8e30" name="RB_PERFCTR_UFC_SEL" stride="1" length="6" variants="A7XX"/> + <array offset="0x8f04" name="RB_PERFCTR_CMP_SEL" stride="1" length="4" variants="A8XX-"/> + <array offset="0x8f10" name="RB_PERFCTR_UFC_SEL" stride="1" length="6" variants="A8XX-"/> + <reg32 offset="0x8e3b" name="RB_SUB_BLOCK_SEL_CNTL_HOST"/> + <reg32 offset="0x8e3d" name="RB_SUB_BLOCK_SEL_CNTL_CD"/> + <reg32 offset="0x8f29" name="RB_UFC_DBG_CNTL" variants="A8XX-"/> <!-- 0x8e3e-0x8e4f invalid --> <!-- GMEM save/restore for preemption: --> - <reg32 offset="0x8e50" name="RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE" pos="0" type="boolean"/> + <reg32 offset="0x8e50" name="RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE" pos="0" type="boolean"/> <!-- address for GMEM save/restore? --> - <reg32 offset="0x8e51" name="RB_UNKNOWN_8E51" type="waddress" align="1"/> - <!-- 0x8e53-0x8e7f invalid --> - <reg32 offset="0x8e79" name="RB_UNKNOWN_8E79" variants="A7XX-" usage="cmd"/> + <reg32 offset="0x8e51" name="RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ADDR" type="waddress" align="1"/> + <reg32 offset="0x8e77" name="RB_SLICE_UFC_PREFETCH_CNTL" variants="A8XX-"/> + <reg32 offset="0x8e78" name="RB_SLICE_UFC_DBG_CNTL" variants="A8XX-"/> + <reg32 offset="0x8e79" name="RB_UNKNOWN_8E79" variants="A7XX" usage="init"/> <!-- 0x8e80-0x8e83 are valid --> <!-- 0x8e84-0x90ff invalid --> @@ -4069,38 +2860,57 @@ to upconvert to 32b float internally? <bitfield name="CLIP_DIST_03_LOC" low="8" high="15" type="uint"/> <bitfield name="CLIP_DIST_47_LOC" low="16" high="23" type="uint"/> </bitset> - <reg32 offset="0x9101" name="VPC_VS_CLIP_CNTL" type="a6xx_vpc_xs_clip_cntl" usage="rp_blit"/> - <reg32 offset="0x9102" name="VPC_GS_CLIP_CNTL" type="a6xx_vpc_xs_clip_cntl" usage="rp_blit"/> - <reg32 offset="0x9103" name="VPC_DS_CLIP_CNTL" type="a6xx_vpc_xs_clip_cntl" usage="rp_blit"/> + <reg32 offset="0x9101" name="VPC_VS_CLIP_CULL_CNTL" type="a6xx_vpc_xs_clip_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9102" name="VPC_GS_CLIP_CULL_CNTL" type="a6xx_vpc_xs_clip_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9103" name="VPC_DS_CLIP_CULL_CNTL" type="a6xx_vpc_xs_clip_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + + <reg32 offset="0x9307" name="VPC_VS_CLIP_CULL_CNTL" type="a6xx_vpc_xs_clip_cntl" variants="A8XX" usage="rp_blit"/> + <reg32 offset="0x9308" name="VPC_GS_CLIP_CULL_CNTL" type="a6xx_vpc_xs_clip_cntl" variants="A8XX" usage="rp_blit"/> + <reg32 offset="0x9309" name="VPC_DS_CLIP_CULL_CNTL" type="a6xx_vpc_xs_clip_cntl" variants="A8XX" usage="rp_blit"/> - <reg32 offset="0x9311" name="VPC_VS_CLIP_CNTL_V2" type="a6xx_vpc_xs_clip_cntl" usage="rp_blit"/> - <reg32 offset="0x9312" name="VPC_GS_CLIP_CNTL_V2" type="a6xx_vpc_xs_clip_cntl" usage="rp_blit"/> - <reg32 offset="0x9313" name="VPC_DS_CLIP_CNTL_V2" type="a6xx_vpc_xs_clip_cntl" usage="rp_blit"/> + <reg32 offset="0x9311" name="VPC_VS_CLIP_CULL_CNTL_V2" type="a6xx_vpc_xs_clip_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9312" name="VPC_GS_CLIP_CULL_CNTL_V2" type="a6xx_vpc_xs_clip_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9313" name="VPC_DS_CLIP_CULL_CNTL_V2" type="a6xx_vpc_xs_clip_cntl" variants="A6XX-A7XX" usage="rp_blit"/> - <bitset name="a6xx_vpc_xs_layer_cntl" inline="yes"> + <bitset name="a6xx_vpc_xs_siv_cntl" inline="yes"> <bitfield name="LAYERLOC" low="0" high="7" type="uint"/> <bitfield name="VIEWLOC" low="8" high="15" type="uint"/> <bitfield name="SHADINGRATELOC" low="16" high="23" type="uint" variants="A7XX-"/> </bitset> - <reg32 offset="0x9104" name="VPC_VS_LAYER_CNTL" type="a6xx_vpc_xs_layer_cntl" usage="rp_blit"/> - <reg32 offset="0x9105" name="VPC_GS_LAYER_CNTL" type="a6xx_vpc_xs_layer_cntl" usage="rp_blit"/> - <reg32 offset="0x9106" name="VPC_DS_LAYER_CNTL" type="a6xx_vpc_xs_layer_cntl" usage="rp_blit"/> + <reg32 offset="0x9104" name="VPC_VS_SIV_CNTL" type="a6xx_vpc_xs_siv_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9105" name="VPC_GS_SIV_CNTL" type="a6xx_vpc_xs_siv_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9106" name="VPC_DS_SIV_CNTL" type="a6xx_vpc_xs_siv_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + + <reg32 offset="0x930a" name="VPC_VS_SIV_CNTL" type="a6xx_vpc_xs_siv_cntl" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x930b" name="VPC_GS_SIV_CNTL" type="a6xx_vpc_xs_siv_cntl" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x930c" name="VPC_DS_SIV_CNTL" type="a6xx_vpc_xs_siv_cntl" variants="A8XX-" usage="rp_blit"/> + + <reg32 offset="0x9314" name="VPC_VS_SIV_CNTL_V2" type="a6xx_vpc_xs_siv_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9315" name="VPC_GS_SIV_CNTL_V2" type="a6xx_vpc_xs_siv_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9316" name="VPC_DS_SIV_CNTL_V2" type="a6xx_vpc_xs_siv_cntl" variants="A6XX-A7XX" usage="rp_blit"/> - <reg32 offset="0x9314" name="VPC_VS_LAYER_CNTL_V2" type="a6xx_vpc_xs_layer_cntl" usage="rp_blit"/> - <reg32 offset="0x9315" name="VPC_GS_LAYER_CNTL_V2" type="a6xx_vpc_xs_layer_cntl" usage="rp_blit"/> - <reg32 offset="0x9316" name="VPC_DS_LAYER_CNTL_V2" type="a6xx_vpc_xs_layer_cntl" usage="rp_blit"/> + <bitset name="a6xx_vpc_rast_stream_cntl" inline="yes"> + <!-- which stream to send to GRAS --> + <bitfield name="STREAM" low="0" high="1" type="uint"/> + <!-- discard primitives before rasterization --> + <bitfield name="DISCARD" pos="2" type="boolean"/> + </bitset> + + <reg32 offset="0x9980" name="VPC_RAST_STREAM_CNTL" type="a6xx_vpc_rast_stream_cntl" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0x9107" name="VPC_RAST_STREAM_CNTL" type="a6xx_vpc_rast_stream_cntl" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x930d" name="VPC_RAST_STREAM_CNTL" type="a6xx_vpc_rast_stream_cntl" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x9317" name="VPC_RAST_STREAM_CNTL_V2" type="a6xx_vpc_rast_stream_cntl" variants="A7XX" usage="rp_blit"/> <reg32 offset="0x9107" name="VPC_UNKNOWN_9107" variants="A6XX" usage="rp_blit"> - <!-- this mirrors PC_RASTER_CNTL::DISCARD, although it seems it's unused --> + <!-- this mirrors VPC_RAST_STREAM_CNTL::DISCARD, although it seems it's unused --> <bitfield name="RASTER_DISCARD" pos="0" type="boolean"/> <bitfield name="UNK2" pos="2" type="boolean"/> </reg32> - <reg32 offset="0x9108" name="VPC_POLYGON_MODE" usage="rp_blit"> - <bitfield name="MODE" low="0" high="1" type="a6xx_polygon_mode"/> - </reg32> - <bitset name="a6xx_primitive_cntl_0" inline="yes"> + <reg32 offset="0x9108" name="VPC_RAST_CNTL" type="a6xx_rast_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x930e" name="VPC_RAST_CNTL" type="a6xx_rast_cntl" variants="A8XX-" usage="rp_blit"/> + <bitset name="a6xx_pc_cntl" inline="yes"> <bitfield name="PRIMITIVE_RESTART" pos="0" type="boolean"/> <bitfield name="PROVOKING_VTX_LAST" pos="1" type="boolean"/> <bitfield name="D3D_VERTEX_ORDERING" pos="2" type="boolean"> @@ -4113,7 +2923,7 @@ to upconvert to 32b float internally? <bitfield name="UNK3" pos="3" type="boolean"/> </bitset> - <bitset name="a6xx_primitive_cntl_5" inline="yes"> + <bitset name="a6xx_gs_param_0" inline="yes"> <doc> geometry shader </doc> @@ -4125,7 +2935,7 @@ to upconvert to 32b float internally? <bitfield name="UNK18" pos="18"/> </bitset> - <bitset name="a6xx_multiview_cntl" inline="yes"> + <bitset name="a6xx_stereo_rendering_cntl" inline="yes"> <bitfield name="ENABLE" pos="0" type="boolean"/> <bitfield name="DISABLEMULTIPOS" pos="1" type="boolean"> <doc> @@ -4139,10 +2949,14 @@ to upconvert to 32b float internally? <bitfield name="VIEWS" low="2" high="6" type="uint"/> </bitset> - <reg32 offset="0x9109" name="VPC_PRIMITIVE_CNTL_0" type="a6xx_primitive_cntl_0" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0x910a" name="VPC_PRIMITIVE_CNTL_5" type="a6xx_primitive_cntl_5" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0x910b" name="VPC_MULTIVIEW_MASK" type="hex" low="0" high="15" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0x910c" name="VPC_MULTIVIEW_CNTL" type="a6xx_multiview_cntl" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0x9109" name="VPC_PC_CNTL" type="a6xx_pc_cntl" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x930f" name="VPC_PC_CNTL" type="a6xx_pc_cntl" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x910a" name="VPC_GS_PARAM_0" type="a6xx_gs_param_0" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x90c0" name="VPC_GS_PARAM_0" type="a6xx_gs_param_0" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x910b" name="VPC_STEREO_RENDERING_VIEWMASK" type="hex" low="0" high="15" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x90c1" name="VPC_STEREO_RENDERING_VIEWMASK" type="hex" low="0" high="15" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x910c" name="VPC_STEREO_RENDERING_CNTL" type="a6xx_stereo_rendering_cntl" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x931a" name="VPC_STEREO_RENDERING_CNTL" type="a6xx_stereo_rendering_cntl" variants="A8XX-" usage="rp_blit"/> <enum name="a6xx_varying_interp_mode"> <value value="0" name="INTERP_SMOOTH"/> @@ -4159,11 +2973,20 @@ to upconvert to 32b float internally? </enum> <!-- 0x9109-0x91ff invalid --> - <array offset="0x9200" name="VPC_VARYING_INTERP" stride="1" length="8" usage="rp_blit"> + <array offset="0x9200" name="VPC_VARYING_INTERP_MODE" stride="1" length="8" variants="A6XX-A7XX" usage="rp_blit"> + <doc>Packed array of a6xx_varying_interp_mode</doc> + <reg32 offset="0x0" name="MODE"/> + </array> + <array offset="0x9208" name="VPC_VARYING_REPLACE_MODE" stride="1" length="8" variants="A6XX-A7XX" usage="rp_blit"> + <doc>Packed array of a6xx_varying_ps_repl_mode</doc> + <reg32 offset="0x0" name="MODE"/> + </array> + + <array offset="0x9240" name="VPC_VARYING_INTERP_MODE" stride="1" length="8" variants="A8XX-" usage="rp_blit"> <doc>Packed array of a6xx_varying_interp_mode</doc> <reg32 offset="0x0" name="MODE"/> </array> - <array offset="0x9208" name="VPC_VARYING_PS_REPL" stride="1" length="8" usage="rp_blit"> + <array offset="0x9248" name="VPC_VARYING_REPLACE_MODE" stride="1" length="8" variants="A8XX-" usage="rp_blit"> <doc>Packed array of a6xx_varying_ps_repl_mode</doc> <reg32 offset="0x0" name="MODE"/> </array> @@ -4172,12 +2995,17 @@ to upconvert to 32b float internally? <reg32 offset="0x9210" name="VPC_UNKNOWN_9210" low="0" high="31" variants="A6XX" usage="cmd"/> <reg32 offset="0x9211" name="VPC_UNKNOWN_9211" low="0" high="31" variants="A6XX" usage="cmd"/> - <array offset="0x9212" name="VPC_VAR" stride="1" length="4" usage="rp_blit"> + <array offset="0x9212" name="VPC_VARYING_LM_TRANSFER_CNTL" stride="1" length="4" variants="A6XX-A7XX" usage="rp_blit"> + <!-- one bit per varying component: --> + <reg32 offset="0" name="DISABLE"/> + </array> + + <array offset="0x9252" name="VPC_VARYING_LM_TRANSFER_CNTL" stride="1" length="4" variants="A8XX-" usage="rp_blit"> <!-- one bit per varying component: --> <reg32 offset="0" name="DISABLE"/> </array> - <reg32 offset="0x9216" name="VPC_SO_CNTL" usage="rp_blit"> + <bitset name="a6xx_vpc_so_mapping_wptr" inline="yes"> <!-- Choose which DWORD to write to. There is an array of (4 * 64) DWORD's, dumped in the devcoredump at @@ -4198,26 +3026,34 @@ to upconvert to 32b float internally? When EmitStreamVertex(N) happens, the HW goes to DWORD 64 * N and then "executes" the next 64 DWORD's. - This field is auto-incremented when VPC_SO_PROG is + This field is auto-incremented when VPC_SO_MAPPING_PORT is written to. --> <bitfield name="ADDR" low="0" high="7" type="hex"/> <!-- clear all A_EN and B_EN bits for all DWORD's --> <bitfield name="RESET" pos="16" type="boolean"/> - </reg32> - <!-- special register, write multiple times to load SO program (not readable) --> - <reg32 offset="0x9217" name="VPC_SO_PROG" usage="rp_blit"> + </bitset> + + <reg32 offset="0x9216" name="VPC_SO_MAPPING_WPTR" type="a6xx_vpc_so_mapping_wptr" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9180" name="VPC_SO_MAPPING_WPTR" type="a6xx_vpc_so_mapping_wptr" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_vpc_so_mapping_port" inline="yes"> <bitfield name="A_BUF" low="0" high="1" type="uint"/> <bitfield name="A_OFF" low="2" high="10" shr="2" type="uint"/> <bitfield name="A_EN" pos="11" type="boolean"/> <bitfield name="B_BUF" low="12" high="13" type="uint"/> <bitfield name="B_OFF" low="14" high="22" shr="2" type="uint"/> <bitfield name="B_EN" pos="23" type="boolean"/> - </reg32> + </bitset> + + <!-- special register, write multiple times to load SO program (not readable) --> + <reg32 offset="0x9217" name="VPC_SO_MAPPING_PORT" type="a6xx_vpc_so_mapping_port" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9181" name="VPC_SO_MAPPING_PORT" type="a6xx_vpc_so_mapping_port" variants="A8XX-" usage="rp_blit"/> - <reg64 offset="0x9218" name="VPC_SO_STREAM_COUNTS" type="waddress" align="32" usage="cmd"/> + <reg64 offset="0x9218" name="VPC_SO_QUERY_BASE" type="waddress" align="32" variants="A6XX-A7XX" usage="cmd"/> + <reg64 offset="0x9182" name="VPC_SO_QUERY_BASE" type="waddress" align="32" variants="A8XX-" usage="cmd"/> - <array offset="0x921a" name="VPC_SO" stride="7" length="4" usage="cmd"> + <array offset="0x921a" name="VPC_SO" stride="7" length="4" variants="A6XX-A7XX" usage="cmd"> <reg64 offset="0" name="BUFFER_BASE" type="waddress" align="32"/> <reg32 offset="2" name="BUFFER_SIZE" low="2" high="31" shr="2"/> <reg32 offset="3" name="BUFFER_STRIDE" low="0" high="9" shr="2"/> @@ -4225,14 +3061,25 @@ to upconvert to 32b float internally? <reg64 offset="5" name="FLUSH_BASE" type="waddress" align="32"/> </array> - <reg32 offset="0x9236" name="VPC_POINT_COORD_INVERT" usage="cmd"> + <array offset="0x9184" name="VPC_SO" stride="7" length="4" variants="A8XX-" usage="cmd"> + <reg64 offset="0" name="BUFFER_BASE" type="waddress" align="32"/> + <reg32 offset="2" name="BUFFER_SIZE" low="2" high="31" shr="2"/> + <reg32 offset="3" name="BUFFER_STRIDE" low="0" high="9" shr="2"/> + <reg32 offset="4" name="BUFFER_OFFSET" low="2" high="31" shr="2"/> + <reg64 offset="5" name="FLUSH_BASE" type="waddress" align="32"/> + </array> + + <bitset name="a6xx_vpc_replace_mode_cntl" inline="yes"> <bitfield name="INVERT" pos="0" type="boolean"/> - </reg32> - <!-- 0x9237-0x92ff invalid --> - <!-- always 0x0 ? --> - <reg32 offset="0x9300" name="VPC_UNKNOWN_9300" low="0" high="2" usage="cmd"/> + </bitset> + + <reg32 offset="0x9236" name="VPC_REPLACE_MODE_CNTL" type="a6xx_vpc_replace_mode_cntl" variants="A6XX-A7XX" usage="cmd"/> + <reg32 offset="0x9310" name="VPC_REPLACE_MODE_CNTL" type="a6xx_vpc_replace_mode_cntl" variants="A8XX-" usage="cmd"/> - <bitset name="a6xx_vpc_xs_pack" inline="yes"> + <reg32 offset="0x9300" name="VPC_ROTATION_CNTL" low="0" high="2" variants="A6XX-A7XX" usage="cmd"/> + <reg32 offset="0x9312" name="VPC_ROTATION_CNTL" low="0" high="2" variants="A8XX-" usage="cmd"/> + + <bitset name="a6xx_vpc_xs_cntl" inline="yes"> <doc> num of varyings plus four for gl_Position (plus one if gl_PointSize) plus # of transform-feedback (streamout) varyings if using the @@ -4249,11 +3096,16 @@ to upconvert to 32b float internally? </doc> </bitfield> </bitset> - <reg32 offset="0x9301" name="VPC_VS_PACK" type="a6xx_vpc_xs_pack" usage="rp_blit"/> - <reg32 offset="0x9302" name="VPC_GS_PACK" type="a6xx_vpc_xs_pack" usage="rp_blit"/> - <reg32 offset="0x9303" name="VPC_DS_PACK" type="a6xx_vpc_xs_pack" usage="rp_blit"/> - <reg32 offset="0x9304" name="VPC_CNTL_0" usage="rp_blit"> + <reg32 offset="0x9301" name="VPC_VS_CNTL" type="a6xx_vpc_xs_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9302" name="VPC_GS_CNTL" type="a6xx_vpc_xs_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9303" name="VPC_DS_CNTL" type="a6xx_vpc_xs_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + + <reg32 offset="0x9300" name="VPC_VS_CNTL" type="a6xx_vpc_xs_cntl" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x9301" name="VPC_GS_CNTL" type="a6xx_vpc_xs_cntl" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x9302" name="VPC_DS_CNTL" type="a6xx_vpc_xs_cntl" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_vpc_ps_cntl" inline="yes"> <bitfield name="NUMNONPOSVAR" low="0" high="7" type="uint"/> <!-- for fixed-function (i.e. no GS) gl_PrimitiveID in FS --> <bitfield name="PRIMIDLOC" low="8" high="15" type="uint"/> @@ -4270,9 +3122,12 @@ to upconvert to 32b float internally? ViewID through the VS. </doc> </bitfield> - </reg32> + </bitset> + + <reg32 offset="0x9304" name="VPC_PS_CNTL" type="a6xx_vpc_ps_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9303" name="VPC_PS_CNTL" type="a6xx_vpc_ps_cntl" variants="A8XX-" usage="rp_blit"/> - <reg32 offset="0x9305" name="VPC_SO_STREAM_CNTL" usage="rp_blit"> + <bitset name="a6xx_vpc_so_cntl" inline="yes"> <!-- It's offset by 1, and 0 means "disabled" --> @@ -4281,82 +3136,147 @@ to upconvert to 32b float internally? <bitfield name="BUF2_STREAM" low="6" high="8" type="uint"/> <bitfield name="BUF3_STREAM" low="9" high="11" type="uint"/> <bitfield name="STREAM_ENABLE" low="15" high="18" type="hex"/> - </reg32> - <reg32 offset="0x9306" name="VPC_SO_DISABLE" usage="rp_blit"> + </bitset> + + <reg32 offset="0x9305" name="VPC_SO_CNTL" type="a6xx_vpc_so_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9304" name="VPC_SO_CNTL" type="a6xx_vpc_so_cntl" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_so_override" inline="yes"> <bitfield name="DISABLE" pos="0" type="boolean"/> - </reg32> - <reg32 offset="0x9307" name="VPC_POLYGON_MODE2" variants="A7XX-" usage="rp_blit"> - <bitfield name="MODE" low="0" high="1" type="a6xx_polygon_mode"/> - </reg32> - <reg32 offset="0x9308" name="VPC_ATTR_BUF_SIZE_GMEM" variants="A7XX-" usage="rp_blit"> - <bitfield name="SIZE_GMEM" low="0" high="31"/> - </reg32> - <reg32 offset="0x9309" name="VPC_ATTR_BUF_BASE_GMEM" variants="A7XX-" usage="rp_blit"> - <bitfield name="BASE_GMEM" low="0" high="31"/> - </reg32> - <reg32 offset="0x9b09" name="PC_ATTR_BUF_SIZE_GMEM" variants="A7XX-" usage="rp_blit"> - <bitfield name="SIZE_GMEM" low="0" high="31"/> - </reg32> + </bitset> + + <reg32 offset="0x9306" name="VPC_SO_OVERRIDE" type="a6xx_so_override" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9305" name="VPC_SO_OVERRIDE" type="a6xx_so_override" variants="A8XX-" usage="rp_blit"/> + + <reg32 offset="0x9807" name="PC_DGEN_SO_OVERRIDE" type="a6xx_so_override" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x9b0a" name="PC_DGEN_SO_OVERRIDE" type="a6xx_so_override" variants="A8XX-" usage="rp_blit"/> + + <reg32 offset="0x9307" name="VPC_PS_RAST_CNTL" type="a6xx_rast_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9306" name="VPC_PS_RAST_CNTL" type="a6xx_rast_cntl" variants="A8XX-" usage="rp_blit"/> + + <reg32 offset="0x9308" name="VPC_ATTR_BUF_GMEM_SIZE" variants="A7XX" type="uint" usage="cmd"/> + <reg32 offset="0x9309" name="VPC_ATTR_BUF_GMEM_BASE" variants="A7XX" type="hex" usage="cmd"/> + + <reg32 offset="0x9314" name="VPC_ATTR_BUF_GMEM_SIZE" variants="A8XX-" type="uint" usage="cmd"/> + <reg32 offset="0x9315" name="VPC_ATTR_BUF_GMEM_BASE" variants="A8XX-" type="hex" usage="cmd"/> + + <reg32 offset="0x9316" name="VPC_POS_BUF_GMEM_SIZE" variants="A8XX-" type="uint" usage="cmd"/> + <reg32 offset="0x9317" name="VPC_POS_BUF_GMEM_BASE" variants="A8XX-" type="hex" usage="cmd"/> + + <reg32 offset="0x9318" name="VPC_BV_POS_BUF_GMEM_SIZE" variants="A8XX-" type="uint" usage="cmd"/> + <reg32 offset="0x9319" name="VPC_BV_POS_BUF_GMEM_BASE" variants="A8XX-" type="hex" usage="cmd"/> + + <reg32 offset="0x9b09" name="PC_ATTR_BUF_GMEM_SIZE" variants="A7XX" type="uint" usage="cmd"/> + <reg32 offset="0x9b16" name="PC_ATTR_BUF_GMEM_SIZE" variants="A8XX-" type="uint" usage="cmd"/> + + <reg32 offset="0x9b17" name="PC_POS_BUF_GMEM_SIZE" variants="A8XX-" type="uint" usage="cmd"/> + <reg32 offset="0x9b18" name="PC_BV_POS_BUF_GMEM_SIZE" variants="A8XX-" type="uint" usage="cmd"/> + + <reg32 offset="0x930a" name="VPC_UNKNOWN_930A" variants="A7XX"/> + + <reg32 offset="0x9313" name="VPC_UNKNOWN_9313" variants="A8XX-"/> + <reg32 offset="0x9e17" name="PC_UNKNOWN_9E17" variants="A8XX-"/> + + <reg32 offset="0x960a" name="VPC_FLATSHADE_MODE_CNTL" variants="A7XX"/> + <reg32 offset="0x9741" name="VPC_FLATSHADE_MODE_CNTL" variants="A8XX-"/> <!-- 0x9307-0x95ff invalid --> <!-- TODO: 0x9600-0x97ff range --> - <reg32 offset="0x9600" name="VPC_DBG_ECO_CNTL" usage="cmd"/> <!-- always 0x0 ? TODO: 0x1fbf37ff valid mask --> - <reg32 offset="0x9601" name="VPC_ADDR_MODE_CNTL" pos="0" type="a5xx_address_mode" usage="cmd"/> - <reg32 offset="0x9602" name="VPC_UNKNOWN_9602" pos="0" usage="cmd"/> <!-- always 0x0 ? --> - <reg32 offset="0x9603" name="VPC_UNKNOWN_9603" low="0" high="26"/> + <reg32 offset="0x9600" name="VPC_DBG_ECO_CNTL" variants="A6XX-A7XX" usage="cmd"/> <!-- always 0x0 ? TODO: 0x1fbf37ff valid mask --> + <reg32 offset="0x9601" name="VPC_ADDR_MODE_CNTL" pos="0" type="a5xx_address_mode" usage="cmd" variants="A6XX"/> + <reg32 offset="0x9680" name="VPC_DBG_ECO_CNTL" variants="A8XX-"/> + <reg32 offset="0x9604" name="VPC_DBG_ECO_CNTL_2" variants="A8XX-"/> + <reg32 offset="0x9742" name="VPC_DBG_ECO_CNTL_1" variants="A8XX-"/> + <reg32 offset="0x9745" name="VPC_DBG_ECO_CNTL_3" variants="A8XX-"/> + <reg32 offset="0x9602" name="VPC_LB_MODE_CNTL" pos="0" variants="A6XX-A7XX" usage="init"/> <!-- always 0x0 ? --> + <reg32 offset="0x9740" name="VPC_LB_MODE_CNTL" pos="0" variants="A8XX-"/> + <reg32 offset="0x9603" name="VPC_STATUS" low="0" high="26" variants="A6XX-A7XX"/> + <reg32 offset="0x9600" name="VPC_STATUS" low="0" high="26" variants="A8XX-"/> <array offset="0x9604" name="VPC_PERFCTR_VPC_SEL" stride="1" length="6" variants="A6XX"/> - <array offset="0x960b" name="VPC_PERFCTR_VPC_SEL" stride="1" length="12" variants="A7XX-"/> - <!-- 0x960a-0x9623 invalid --> - <!-- TODO: regs from 0x9624-0x963a --> - <!-- 0x963b-0x97ff invalid --> + <array offset="0x960b" name="VPC_PERFCTR_VPC_SEL" stride="1" length="12" variants="A7XX"/> + <array offset="0x9670" name="VPC_PERFCTR_VPC_SEL_2" stride="1" length="12" variants="A8XX-"/> + <array offset="0x9690" name="VPC_PERFCTR_VPC_SEL" stride="1" length="12" variants="A8XX-"/> + <array offset="0x9750" name="VPC_PERFCTR_VPC_SEL_1" stride="1" length="12" variants="A8XX-"/> - <reg32 offset="0x9800" name="PC_TESS_NUM_VERTEX" low="0" high="5" type="uint" usage="rp_blit"/> + <reg64 offset="0x9634" name="VPC_CONTEXT_SWITCH_SO_SAVE_ADDR" type="waddress" variants="A6XX-A7XX"/> + <reg64 offset="0x9602" name="VPC_CONTEXT_SWITCH_SO_SAVE_ADDR" type="waddress" variants="A8XX-"/> - <!-- always 0x0 ? --> - <reg32 offset="0x9801" name="PC_HS_INPUT_SIZE" usage="rp_blit"> + <reg32 offset="0x980b" name="PC_UNKNOWN_980B" variants="A8XX-"/> + + <reg32 offset="0x9800" name="PC_HS_PARAM_0" low="0" high="5" type="uint" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b10" name="PC_HS_PARAM_0" low="0" high="5" type="uint" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_pc_hs_param_1" inline="yes"> <bitfield name="SIZE" low="0" high="10" type="uint"/> <bitfield name="UNK13" pos="13"/> - </reg32> + </bitset> + + <reg32 offset="0x9801" name="PC_HS_PARAM_1" type="a6xx_pc_hs_param_1" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b11" name="PC_HS_PARAM_1" type="a6xx_pc_hs_param_1" variants="A8XX-" usage="rp_blit"/> - <reg32 offset="0x9802" name="PC_TESS_CNTL" usage="rp_blit"> + <bitset name="a6xx_pc_ds_param" inline="yes"> <bitfield name="SPACING" low="0" high="1" type="a6xx_tess_spacing"/> <bitfield name="OUTPUT" low="2" high="3" type="a6xx_tess_output"/> - </reg32> + </bitset> + + <reg32 offset="0x9802" name="PC_DS_PARAM" type="a6xx_pc_ds_param" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b12" name="PC_DS_PARAM" type="a6xx_pc_ds_param" variants="A8XX-" usage="rp_blit"/> - <reg32 offset="0x9803" name="PC_RESTART_INDEX" low="0" high="31" type="uint" usage="rp_blit"/> - <reg32 offset="0x9804" name="PC_MODE_CNTL" low="0" high="7" usage="rp_blit"/> + <reg32 offset="0x9803" name="PC_RESTART_INDEX" low="0" high="31" type="uint" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b15" name="PC_RESTART_INDEX" low="0" high="31" type="uint" variants="A8XX-" usage="rp_blit"/> + + <reg32 offset="0x9804" name="PC_MODE_CNTL" low="0" high="7" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b00" name="PC_MODE_CNTL" low="0" high="14" variants="A8XX" usage="rp_blit"/> <reg32 offset="0x9805" name="PC_POWER_CNTL" low="0" high="2" usage="rp_blit"/> - <reg32 offset="0x9806" name="PC_PS_CNTL" usage="rp_blit"> + <bitset name="a6xx_pc_ps_cntl" inline="yes"> <bitfield name="PRIMITIVEIDEN" pos="0" type="boolean"/> - </reg32> + </bitset> - <!-- New in a6xx gen3+ --> - <reg32 offset="0x9808" name="PC_SO_STREAM_CNTL" usage="rp_blit"> + <reg32 offset="0x9806" name="PC_PS_CNTL" type="a6xx_pc_ps_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b06" name="PC_PS_CNTL" type="a6xx_pc_ps_cntl" variants="A8XX-" usage="rp_blit"/> + + <bitset name="a6xx_pc_dgen_so_cntl" inline="yes"> <bitfield name="STREAM_ENABLE" low="15" high="18" type="hex"/> - </reg32> + </bitset> + + <!-- New in a6xx gen3+ --> + <reg32 offset="0x9808" name="PC_DGEN_SO_CNTL" type="a6xx_pc_dgen_so_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b0b" name="PC_DGEN_SO_CNTL" type="a6xx_pc_dgen_so_cntl" variants="A8XX-" usage="rp_blit"/> - <reg32 offset="0x980a" name="PC_DGEN_SU_CONSERVATIVE_RAS_CNTL"> + <bitset name="a6xx_pc_dgen_su_conservative_ras_cntl" inline="yes"> <bitfield name="CONSERVATIVERASEN" pos="0" type="boolean"/> + </bitset> + + <reg32 offset="0x980a" name="PC_DGEN_SU_CONSERVATIVE_RAS_CNTL" type="a6xx_pc_dgen_su_conservative_ras_cntl" variants="A6XX-A7XX"/> + <reg32 offset="0x9b08" name="PC_DGEN_SU_CONSERVATIVE_RAS_CNTL" type="a6xx_pc_dgen_su_conservative_ras_cntl" variants="A8XX-"/> + + <reg32 offset="0x9b0c" name="PC_VS_INPUT_CNTL" variants="A8XX-" usage="rp_blit"> + <bitfield name="INSTR_CNT" low="0" high="5" type="uint"/> + <bitfield name="SIDEBAND_CNT" low="6" high="8" type="uint"/> </reg32> - <!-- 0x980b-0x983f invalid --> <!-- 0x9840 - 0x9842 are not readable --> - <reg32 offset="0x9840" name="PC_DRAW_CMD"> + <bitset name="a6xx_draw_initiator" inline="yes"> <bitfield name="STATE_ID" low="0" high="7"/> - </reg32> + </bitset> - <reg32 offset="0x9841" name="PC_DISPATCH_CMD"> - <bitfield name="STATE_ID" low="0" high="7"/> - </reg32> + <reg32 offset="0x9840" name="PC_DRAW_INITIATOR" type="a6xx_draw_initiator" variants="A6XX-A7XX"/> + <reg32 offset="0x9841" name="PC_KERNEL_INITIATOR" type="a6xx_draw_initiator" variants="A6XX-A7XX"/> - <reg32 offset="0x9842" name="PC_EVENT_CMD"> + <reg32 offset="0x9800" name="PC_DRAW_INITIATOR" type="a6xx_draw_initiator" variants="A8XX-"/> + <reg32 offset="0x9801" name="PC_KERNEL_INITIATOR" type="a6xx_draw_initiator" variants="A8XX-"/> + + <bitset name="a6xx_event_initiator" inline="yes"> <!-- I think only the low bit is actually used? --> <bitfield name="STATE_ID" low="16" high="23"/> <bitfield name="EVENT" low="0" high="6" type="vgt_event_type"/> - </reg32> + </bitset> + + <reg32 offset="0x9842" name="PC_EVENT_INITIATOR" type="a6xx_event_initiator" variants="A6XX-A7XX"/> + <reg32 offset="0x9802" name="PC_EVENT_INITIATOR" type="a6xx_event_initiator" variants="A8XX-"/> <!-- 0x9880 written in a lot of places by SQE, same value gets written @@ -4367,47 +3287,27 @@ to upconvert to 32b float internally? <!-- 0x9843-0x997f invalid --> - <reg32 offset="0x9981" name="PC_POLYGON_MODE" variants="A6XX" usage="rp_blit"> - <bitfield name="MODE" low="0" high="1" type="a6xx_polygon_mode"/> - </reg32> - <reg32 offset="0x9809" name="PC_POLYGON_MODE" variants="A7XX-" usage="rp_blit"> - <bitfield name="MODE" low="0" high="1" type="a6xx_polygon_mode"/> - </reg32> - - <reg32 offset="0x9980" name="PC_RASTER_CNTL" variants="A6XX" usage="rp_blit"> - <!-- which stream to send to GRAS --> - <bitfield name="STREAM" low="0" high="1" type="uint"/> - <!-- discard primitives before rasterization --> - <bitfield name="DISCARD" pos="2" type="boolean"/> - </reg32> - <!-- VPC_RASTER_CNTL --> - <reg32 offset="0x9107" name="PC_RASTER_CNTL" variants="A7XX-" usage="rp_blit"> - <!-- which stream to send to GRAS --> - <bitfield name="STREAM" low="0" high="1" type="uint"/> - <!-- discard primitives before rasterization --> - <bitfield name="DISCARD" pos="2" type="boolean"/> - </reg32> - <reg32 offset="0x9317" name="PC_RASTER_CNTL_V2" variants="A7XX-" usage="rp_blit"> - <!-- which stream to send to GRAS --> - <bitfield name="STREAM" low="0" high="1" type="uint"/> - <!-- discard primitives before rasterization --> - <bitfield name="DISCARD" pos="2" type="boolean"/> - </reg32> + <reg32 offset="0x9981" name="PC_DGEN_RAST_CNTL" type="a6xx_rast_cntl" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0x9809" name="PC_DGEN_RAST_CNTL" type="a6xx_rast_cntl" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0x9812" name="PC_DGEN_RAST_CNTL" type="a6xx_rast_cntl" variants="A8XX" usage="rp_blit"/> <!-- Both are a750+. Probably needed to correctly overlap execution of several draws. --> - <reg32 offset="0x9885" name="PC_TESS_PARAM_SIZE" variants="A7XX-" usage="cmd"/> + <reg32 offset="0x9885" name="PC_HS_BUFFER_SIZE" variants="A7XX" usage="cmd"/> + <reg32 offset="0x9814" name="PC_HS_BUFFER_SIZE" variants="A8XX-" usage="cmd"/> <!-- Blob adds a bit more space {0x10, 0x20, 0x30, 0x40} bytes, but the meaning of this additional space is not known. --> - <reg32 offset="0x9886" name="PC_TESS_FACTOR_SIZE" variants="A7XX-" usage="cmd"/> + <reg32 offset="0x9886" name="PC_TF_BUFFER_SIZE" variants="A7XX" usage="cmd"/> + <reg32 offset="0x9815" name="PC_TF_BUFFER_SIZE" variants="A8XX-" usage="cmd"/> <!-- 0x9982-0x9aff invalid --> - <reg32 offset="0x9b00" name="PC_PRIMITIVE_CNTL_0" type="a6xx_primitive_cntl_0" usage="rp_blit"/> + <reg32 offset="0x9b00" name="PC_CNTL" type="a6xx_pc_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b01" name="PC_CNTL" type="a6xx_pc_cntl" variants="A8XX-" usage="rp_blit"/> - <bitset name="a6xx_xs_out_cntl" inline="yes"> + <bitset name="a6xx_pc_xs_cntl" inline="yes"> <doc> num of varyings plus four for gl_Position (plus one if gl_PointSize) plus # of transform-feedback (streamout) varyings if using the @@ -4417,19 +3317,25 @@ to upconvert to 32b float internally? <bitfield name="PSIZE" pos="8" type="boolean"/> <bitfield name="LAYER" pos="9" type="boolean"/> <bitfield name="VIEW" pos="10" type="boolean"/> - <!-- note: PC_VS_OUT_CNTL doesn't have the PRIMITIVE_ID bit --> + <!-- note: PC_VS_CNTL doesn't have the PRIMITIVE_ID bit --> + <!-- since HS can't output anything, only PRIMITIVE_ID is valid --> <bitfield name="PRIMITIVE_ID" pos="11" type="boolean"/> <bitfield name="CLIP_MASK" low="16" high="23" type="uint"/> <bitfield name="SHADINGRATE" pos="24" type="boolean" variants="A7XX-"/> </bitset> - <reg32 offset="0x9b01" name="PC_VS_OUT_CNTL" type="a6xx_xs_out_cntl" usage="rp_blit"/> - <reg32 offset="0x9b02" name="PC_GS_OUT_CNTL" type="a6xx_xs_out_cntl" usage="rp_blit"/> - <!-- since HS can't output anything, only PRIMITIVE_ID is valid --> - <reg32 offset="0x9b03" name="PC_HS_OUT_CNTL" type="a6xx_xs_out_cntl" usage="rp_blit"/> - <reg32 offset="0x9b04" name="PC_DS_OUT_CNTL" type="a6xx_xs_out_cntl" usage="rp_blit"/> + <reg32 offset="0x9b01" name="PC_VS_CNTL" type="a6xx_pc_xs_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b02" name="PC_GS_CNTL" type="a6xx_pc_xs_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b03" name="PC_HS_CNTL" type="a6xx_pc_xs_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b04" name="PC_DS_CNTL" type="a6xx_pc_xs_cntl" variants="A6XX-A7XX" usage="rp_blit"/> - <reg32 offset="0x9b05" name="PC_PRIMITIVE_CNTL_5" type="a6xx_primitive_cntl_5" usage="rp_blit"/> + <reg32 offset="0x9b02" name="PC_VS_CNTL" type="a6xx_pc_xs_cntl" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x9b03" name="PC_GS_CNTL" type="a6xx_pc_xs_cntl" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x9b04" name="PC_HS_CNTL" type="a6xx_pc_xs_cntl" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0x9b05" name="PC_DS_CNTL" type="a6xx_pc_xs_cntl" variants="A8XX-" usage="rp_blit"/> + + <reg32 offset="0x9b05" name="PC_GS_PARAM_0" type="a6xx_gs_param_0" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b13" name="PC_GS_PARAM_0" type="a6xx_gs_param_0" variants="A8XX-" usage="rp_blit"/> <reg32 offset="0x9b06" name="PC_PRIMITIVE_CNTL_6" variants="A6XX" usage="rp_blit"> <doc> @@ -4438,68 +3344,100 @@ to upconvert to 32b float internally? <bitfield name="STRIDE_IN_VPC" low="0" high="10" type="uint"/> </reg32> - <reg32 offset="0x9b07" name="PC_MULTIVIEW_CNTL" type="a6xx_multiview_cntl" usage="rp_blit"/> + <reg32 offset="0x9b07" name="PC_STEREO_RENDERING_CNTL" type="a6xx_stereo_rendering_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b09" name="PC_STEREO_RENDERING_CNTL" type="a6xx_stereo_rendering_cntl" variants="A8XX-" usage="rp_blit"/> <!-- mask of enabled views, doesn't exist on A630 --> - <reg32 offset="0x9b08" name="PC_MULTIVIEW_MASK" type="hex" low="0" high="15" usage="rp_blit"/> + <reg32 offset="0x9b08" name="PC_STEREO_RENDERING_VIEWMASK" type="hex" low="0" high="15" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0x9b0d" name="PC_STEREO_RENDERING_VIEWMASK" type="hex" low="0" high="15" variants="A8XX-" usage="rp_blit"/> <!-- 0x9b09-0x9bff invalid --> <reg32 offset="0x9c00" name="PC_2D_EVENT_CMD"> <!-- special register (but note first 8 bits can be written/read) --> <bitfield name="EVENT" low="0" high="6" type="vgt_event_type"/> <bitfield name="STATE_ID" low="8" high="15"/> </reg32> - <!-- 0x9c01-0x9dff invalid --> - <!-- TODO: 0x9e00-0xa000 range incomplete --> - <reg32 offset="0x9e00" name="PC_DBG_ECO_CNTL"/> - <reg32 offset="0x9e01" name="PC_ADDR_MODE_CNTL" type="a5xx_address_mode"/> - <reg64 offset="0x9e04" name="PC_DRAW_INDX_BASE"/> - <reg32 offset="0x9e06" name="PC_DRAW_FIRST_INDX" type="uint"/> - <reg32 offset="0x9e07" name="PC_DRAW_MAX_INDICES" type="uint"/> - <reg64 offset="0x9e08" name="PC_TESSFACTOR_ADDR" variants="A6XX" type="waddress" align="32" usage="cmd"/> - <reg64 offset="0x9810" name="PC_TESSFACTOR_ADDR" variants="A7XX-" type="waddress" align="32" usage="cmd"/> - - <reg32 offset="0x9e0b" name="PC_DRAW_INITIATOR" type="vgt_draw_initiator_a4xx"> + + <reg32 offset="0x9e50" name="PC_CHICKEN_BITS_1" variants="A8XX-"/> + <reg32 offset="0x9f20" name="PC_CHICKEN_BITS_2" variants="A8XX-"/> + <reg32 offset="0x9e22" name="PC_CHICKEN_BITS_3" variants="A8XX-"/> + <reg32 offset="0x9e23" name="PC_CHICKEN_BITS_4" variants="A8XX-"/> + <reg32 offset="0x9f23" name="PC_CHICKEN_BITS_5" variants="A8XX-"/> + + <reg32 offset="0x9e00" name="PC_DBG_ECO_CNTL" variants="A6XX-A7XX"/> + <reg32 offset="0x9e53" name="PC_DBG_ECO_CNTL" variants="A8XX-"/> + <reg32 offset="0x9e01" name="PC_ADDR_MODE_CNTL" type="a5xx_address_mode" variants="A6XX"/> + <reg64 offset="0x9e04" name="PC_DMA_BASE" type="address" variants="A6XX-A7XX"/> + <reg32 offset="0x9e06" name="PC_DMA_OFFSET" type="uint" variants="A6XX-A7XX"/> + <reg32 offset="0x9e07" name="PC_DMA_SIZE" type="uint" variants="A6XX-A7XX"/> + + <reg64 offset="0x9e06" name="PC_DMA_BASE" type="address" variants="A8XX-"/> + <reg32 offset="0x9e08" name="PC_DMA_OFFSET" type="uint" variants="A8XX-"/> + <reg32 offset="0x9e09" name="PC_DMA_SIZE" type="uint" variants="A8XX-"/> + + <reg64 offset="0x9e08" name="PC_TESS_BASE" variants="A6XX" type="waddress" align="32" usage="cmd"/> + <reg64 offset="0x9810" name="PC_TESS_BASE" variants="A7XX" type="waddress" align="32" usage="cmd"/> + <reg64 offset="0x9816" name="PC_TESS_BASE" variants="A8XX-" type="waddress" align="32" usage="cmd"/> + + <reg32 offset="0x9e0b" name="PC_DRAWCALL_CNTL" type="vgt_draw_initiator_a4xx" variants="A6XX-A7XX"> <doc> Possibly not really "initiating" the draw but the layout is similar to VGT_DRAW_INITIATOR on older gens </doc> </reg32> - <reg32 offset="0x9e0c" name="PC_DRAW_NUM_INSTANCES" type="uint"/> - <reg32 offset="0x9e0d" name="PC_DRAW_NUM_INDICES" type="uint"/> + <reg32 offset="0x9e0c" name="PC_DRAWCALL_INSTANCE_NUM" type="uint" variants="A6XX-A7XX"/> + <reg32 offset="0x9e0d" name="PC_DRAWCALL_SIZE" type="uint" variants="A6XX-A7XX"/> + + <reg32 offset="0x9e00" name="PC_DRAWCALL_CNTL" type="vgt_draw_initiator_a4xx" variants="A8XX-"/> + <reg32 offset="0x9e01" name="PC_DRAWCALL_INSTANCE_NUM" type="uint" variants="A8XX-"/> + <reg32 offset="0x9e02" name="PC_DRAWCALL_SIZE" type="uint" variants="A8XX-"/> <!-- These match the contents of CP_SET_BIN_DATA (not written directly) --> - <reg32 offset="0x9e11" name="PC_VSTREAM_CONTROL"> + <bitset name="a6xx_pc_vis_stream_cntl" inline="yes"> <bitfield name="UNK0" low="0" high="15"/> <bitfield name="VSC_SIZE" low="16" high="21" type="uint"/> <bitfield name="VSC_N" low="22" high="26" type="uint"/> - </reg32> - <reg64 offset="0x9e12" name="PC_BIN_PRIM_STRM" type="waddress" align="32"/> - <reg64 offset="0x9e14" name="PC_BIN_DRAW_STRM" type="waddress" align="32"/> + </bitset> - <reg32 offset="0x9e1c" name="PC_VISIBILITY_OVERRIDE"> + <reg32 offset="0x9e11" name="PC_VIS_STREAM_CNTL" type="a6xx_pc_vis_stream_cntl" variants="A6XX-A7XX"/> + <reg64 offset="0x9e12" name="PC_PVIS_STREAM_BIN_BASE" type="waddress" align="32" variants="A6XX-A7XX"/> + <reg64 offset="0x9e14" name="PC_DVIS_STREAM_BIN_BASE" type="waddress" align="32" variants="A6XX-A7XX"/> + + <reg32 offset="0x9e0a" name="PC_AUTO_VERTEX_STRIDE"/> + <reg32 offset="0x9e0d" name="PC_VIS_STREAM_CNTL" type="a6xx_pc_vis_stream_cntl" variants="A8XX-"/> + <reg64 offset="0x9e0e" name="PC_PVIS_STREAM_BIN_BASE" type="waddress" align="32" variants="A8XX-"/> + <reg64 offset="0x9e10" name="PC_DVIS_STREAM_BIN_BASE" type="waddress" align="32" variants="A8XX-"/> + + <bitset name="a6xx_pc_drawcall_cntl_override" inline="yes"> <doc>Written by CP_SET_VISIBILITY_OVERRIDE handler</doc> <bitfield name="OVERRIDE" pos="0" type="boolean"/> - </reg32> + </bitset> + + <reg32 offset="0x9e1c" name="PC_DRAWCALL_CNTL_OVERRIDE" type="a6xx_pc_drawcall_cntl_override" variants="A6XX-A7XX"/> + <reg32 offset="0x9e04" name="PC_DRAWCALL_CNTL_OVERRIDE" type="a6xx_pc_drawcall_cntl_override" variants="A8XX-"/> - <reg32 offset="0x9e24" name="PC_UNKNOWN_9E24" variants="A7XX-" usage="cmd"/> + <reg32 offset="0x9e24" name="PC_UNKNOWN_9E24" variants="A7XX-" usage="init"/> <array offset="0x9e34" name="PC_PERFCTR_PC_SEL" stride="1" length="8" variants="A6XX"/> - <array offset="0x9e42" name="PC_PERFCTR_PC_SEL" stride="1" length="16" variants="A7XX-"/> + <array offset="0x9e42" name="PC_PERFCTR_PC_SEL" stride="1" length="16" variants="A7XX"/> + <array offset="0x9e30" name="PC_PERFCTR_PC_SEL" stride="1" length="16" variants="A8XX-"/> + <array offset="0x9f00" name="PC_SLICE_PERFCTR_PC_SEL" stride="1" length="16" variants="A8XX-"/> <!-- always 0x0 --> - <reg32 offset="0x9e72" name="PC_UNKNOWN_9E72" usage="cmd"/> + <reg32 offset="0x9e72" name="PC_CONTEXT_SWITCH_GFX_PREEMPTION_MODE" variants="A6XX-A7XX" usage="init"/> + <reg32 offset="0x9e63" name="PC_CONTEXT_SWITCH_GFX_PREEMPTION_MODE" variants="A8XX-"/> + <reg32 offset="0x9e64" name="PC_CONTEXT_SWITCH_STABILIZE_CNTL_1" variants="A8XX-"/> - <reg32 offset="0xa000" name="VFD_CONTROL_0" usage="rp_blit"> + <reg32 offset="0xa000" name="VFD_CNTL_0" usage="rp_blit"> <bitfield name="FETCH_CNT" low="0" high="5" type="uint"/> <bitfield name="DECODE_CNT" low="8" high="13" type="uint"/> </reg32> - <reg32 offset="0xa001" name="VFD_CONTROL_1" usage="rp_blit"> + <reg32 offset="0xa001" name="VFD_CNTL_1" usage="rp_blit"> <bitfield name="REGID4VTX" low="0" high="7" type="a3xx_regid"/> <bitfield name="REGID4INST" low="8" high="15" type="a3xx_regid"/> <bitfield name="REGID4PRIMID" low="16" high="23" type="a3xx_regid"/> <!-- only used for VS in non-multi-position-output case --> <bitfield name="REGID4VIEWID" low="24" high="31" type="a3xx_regid"/> </reg32> - <reg32 offset="0xa002" name="VFD_CONTROL_2" usage="rp_blit"> + <reg32 offset="0xa002" name="VFD_CNTL_2" usage="rp_blit"> <bitfield name="REGID_HSRELPATCHID" low="0" high="7" type="a3xx_regid"> <doc> This is the ID of the current patch within the @@ -4512,32 +3450,32 @@ to upconvert to 32b float internally? </bitfield> <bitfield name="REGID_INVOCATIONID" low="8" high="15" type="a3xx_regid"/> </reg32> - <reg32 offset="0xa003" name="VFD_CONTROL_3" usage="rp_blit"> + <reg32 offset="0xa003" name="VFD_CNTL_3" usage="rp_blit"> <bitfield name="REGID_DSPRIMID" low="0" high="7" type="a3xx_regid"/> <bitfield name="REGID_DSRELPATCHID" low="8" high="15" type="a3xx_regid"/> <bitfield name="REGID_TESSX" low="16" high="23" type="a3xx_regid"/> <bitfield name="REGID_TESSY" low="24" high="31" type="a3xx_regid"/> </reg32> - <reg32 offset="0xa004" name="VFD_CONTROL_4" usage="rp_blit"> + <reg32 offset="0xa004" name="VFD_CNTL_4" usage="rp_blit"> <bitfield name="UNK0" low="0" high="7" type="a3xx_regid"/> </reg32> - <reg32 offset="0xa005" name="VFD_CONTROL_5" usage="rp_blit"> + <reg32 offset="0xa005" name="VFD_CNTL_5" usage="rp_blit"> <bitfield name="REGID_GSHEADER" low="0" high="7" type="a3xx_regid"/> <bitfield name="UNK8" low="8" high="15" type="a3xx_regid"/> </reg32> - <reg32 offset="0xa006" name="VFD_CONTROL_6" usage="rp_blit"> + <reg32 offset="0xa006" name="VFD_CNTL_6" usage="rp_blit"> <!-- True if gl_PrimitiveID is read via the FS --> <bitfield name="PRIMID4PSEN" pos="0" type="boolean"/> </reg32> - <reg32 offset="0xa007" name="VFD_MODE_CNTL" usage="cmd"> + <reg32 offset="0xa007" name="VFD_RENDER_MODE" usage="cmd"> <bitfield name="RENDER_MODE" low="0" high="2" type="a6xx_render_mode"/> </reg32> - <reg32 offset="0xa008" name="VFD_MULTIVIEW_CNTL" type="a6xx_multiview_cntl" usage="rp_blit"/> - <reg32 offset="0xa009" name="VFD_ADD_OFFSET" usage="cmd"> + <reg32 offset="0xa008" name="VFD_STEREO_RENDERING_CNTL" type="a6xx_stereo_rendering_cntl" usage="rp_blit"/> + <reg32 offset="0xa009" name="VFD_MODE_CNTL" usage="cmd"> <!-- add VFD_INDEX_OFFSET to REGID4VTX --> <bitfield name="VERTEX" pos="0" type="boolean"/> <!-- add VFD_INSTANCE_START_OFFSET to REGID4INST --> @@ -4546,14 +3484,14 @@ to upconvert to 32b float internally? <reg32 offset="0xa00e" name="VFD_INDEX_OFFSET" usage="rp_blit"/> <reg32 offset="0xa00f" name="VFD_INSTANCE_START_OFFSET" usage="rp_blit"/> - <array offset="0xa010" name="VFD_FETCH" stride="4" length="32" usage="rp_blit"> + <array offset="0xa010" name="VFD_VERTEX_BUFFER" stride="4" length="32" usage="rp_blit"> <reg64 offset="0x0" name="BASE" type="address" align="1"/> <reg32 offset="0x2" name="SIZE" type="uint"/> <reg32 offset="0x3" name="STRIDE" low="0" high="11" type="uint"/> </array> - <array offset="0xa090" name="VFD_DECODE" stride="2" length="32" usage="rp_blit"> + <array offset="0xa090" name="VFD_FETCH_INSTR" stride="2" length="32" usage="rp_blit"> <reg32 offset="0x0" name="INSTR"> - <!-- IDX and byte OFFSET into VFD_FETCH --> + <!-- IDX and byte OFFSET into VFD_VERTEX_BUFFER --> <bitfield name="IDX" low="0" high="4" type="uint"/> <bitfield name="OFFSET" low="5" high="16"/> <bitfield name="INSTANCED" pos="17" type="boolean"/> @@ -4573,11 +3511,15 @@ to upconvert to 32b float internally? <reg32 offset="0xa0f8" name="VFD_POWER_CNTL" low="0" high="2" usage="rp_blit"/> - <reg32 offset="0xa600" name="VFD_UNKNOWN_A600" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xa600" name="VFD_DBG_ECO_CNTL" variants="A7XX-" usage="init"/> - <reg32 offset="0xa601" name="VFD_ADDR_MODE_CNTL" type="a5xx_address_mode"/> + <reg32 offset="0xa601" name="VFD_ADDR_MODE_CNTL" type="a5xx_address_mode" variants="A6XX"/> <array offset="0xa610" name="VFD_PERFCTR_VFD_SEL" stride="1" length="8" variants="A6XX"/> <array offset="0xa610" name="VFD_PERFCTR_VFD_SEL" stride="1" length="16" variants="A7XX-"/> + <reg32 offset="0xa639" name="VFD_CB_BV_THRESHOLD" variants="A8XX-"/> + <reg32 offset="0xa63a" name="VFD_CB_BR_THRESHOLD" variants="A8XX-"/> + <reg32 offset="0xa63b" name="VFD_CB_BUSY_REQ_CNT" variants="A8XX-"/> + <reg32 offset="0xa63c" name="VFD_CB_LP_REQ_CNT" variants="A8XX-"/> <!-- Note: this seems to always be paired with another bit in another @@ -4588,7 +3530,7 @@ to upconvert to 32b float internally? <value value="1" name="THREAD128"/> </enum> - <bitset name="a6xx_sp_xs_ctrl_reg0" inline="yes"> + <bitset name="a6xx_sp_xs_cntl_0" inline="yes"> <!-- if set to SINGLE, only use 1 concurrent wave on each SP --> <bitfield name="THREADMODE" pos="0" type="a3xx_threadmode"/> <!-- @@ -4620,7 +3562,7 @@ to upconvert to 32b float internally? --> <bitfield name="BINDLESS_TEX" pos="0" type="boolean"/> <bitfield name="BINDLESS_SAMP" pos="1" type="boolean"/> - <bitfield name="BINDLESS_IBO" pos="2" type="boolean"/> + <bitfield name="BINDLESS_UAV" pos="2" type="boolean"/> <bitfield name="BINDLESS_UBO" pos="3" type="boolean"/> <bitfield name="ENABLED" pos="8" type="boolean"/> @@ -4630,17 +3572,15 @@ to upconvert to 32b float internally? --> <bitfield name="NTEX" low="9" high="16" type="uint"/> <bitfield name="NSAMP" low="17" high="21" type="uint"/> - <bitfield name="NIBO" low="22" high="28" type="uint"/> + <bitfield name="NUAV" low="22" high="28" type="uint"/> </bitset> - <bitset name="a6xx_sp_xs_prim_cntl" inline="yes"> + <bitset name="a6xx_sp_xs_output_cntl" inline="yes"> <!-- # of VS outputs including pos/psize --> <bitfield name="OUT" low="0" high="5" type="uint"/> - <!-- FLAGS_REGID only for GS --> - <bitfield name="FLAGS_REGID" low="6" high="13" type="a3xx_regid"/> </bitset> - <reg32 offset="0xa800" name="SP_VS_CTRL_REG0" type="a6xx_sp_xs_ctrl_reg0" usage="rp_blit"> + <reg32 offset="0xa800" name="SP_VS_CNTL_0" type="a6xx_sp_xs_cntl_0" usage="rp_blit"> <!-- This field actually controls all geometry stages. TCS, TES, and GS must have the same mergedregs setting as VS. @@ -4665,10 +3605,10 @@ to upconvert to 32b float internally? </reg32> <!-- bitmask of true/false conditions for VS brac.N instructions, bit N corresponds to brac.N --> - <reg32 offset="0xa801" name="SP_VS_BRANCH_COND" type="hex"/> + <reg32 offset="0xa801" name="SP_VS_BOOLEAN_CF_MASK" type="hex"/> <!-- # of VS outputs including pos/psize --> - <reg32 offset="0xa802" name="SP_VS_PRIMITIVE_CNTL" type="a6xx_sp_xs_prim_cntl" usage="rp_blit"/> - <array offset="0xa803" name="SP_VS_OUT" stride="1" length="16" usage="rp_blit"> + <reg32 offset="0xa802" name="SP_VS_OUTPUT_CNTL" type="a6xx_sp_xs_output_cntl" usage="rp_blit"/> + <array offset="0xa803" name="SP_VS_OUTPUT" stride="1" length="16" usage="rp_blit"> <reg32 offset="0x0" name="REG"> <bitfield name="A_REGID" low="0" high="7" type="a3xx_regid"/> <bitfield name="A_COMPMASK" low="8" high="11" type="hex"/> @@ -4678,12 +3618,12 @@ to upconvert to 32b float internally? </array> <!-- Starting with a5xx, position/psize outputs from shader end up in the - SP_VS_OUT map, with highest OUTLOCn position. (Generally they are + SP_VS_OUTPUT map, with highest OUTLOCn position. (Generally they are the last entries too, except when gl_PointCoord is used, blob inserts an extra varying after, but with a lower OUTLOC position. If present, psize is last, preceded by position. --> - <array offset="0xa813" name="SP_VS_VPC_DST" stride="1" length="8" usage="rp_blit"> + <array offset="0xa813" name="SP_VS_VPC_DEST" stride="1" length="8" usage="rp_blit"> <reg32 offset="0x0" name="REG"> <bitfield name="OUTLOC0" low="0" high="7" type="uint"/> <bitfield name="OUTLOC1" low="8" high="15" type="uint"/> @@ -4752,7 +3692,7 @@ to upconvert to 32b float internally? </bitfield> </bitset> - <bitset name="a6xx_sp_xs_pvt_mem_hw_stack_offset" inline="yes"> + <bitset name="a6xx_sp_xs_pvt_mem_stack_offset" inline="yes"> <doc> This seems to be be the equivalent of HWSTACKOFFSET in a3xx. The ldp/stp offset formula above isn't affected by @@ -4763,18 +3703,29 @@ to upconvert to 32b float internally? <bitfield name="OFFSET" low="0" high="18" shr="11"/> </bitset> - <reg32 offset="0xa81b" name="SP_VS_OBJ_FIRST_EXEC_OFFSET" type="uint" usage="rp_blit"/> - <reg64 offset="0xa81c" name="SP_VS_OBJ_START" type="address" align="32" usage="rp_blit"/> + <bitset name="a6xx_sp_xs_hysteresis" inline="yes"> + <doc>Same on a6xx/a7xx, UMD should not need to write this</doc> + </bitset> + + <bitset name="a8xx_sp_xs_hysteresis" inline="yes"> + <doc>UMD needs to write in some cases</doc> + <!-- seen 0x400, 0xc00, 0x1000, 0x1c00, 0x1000, 0x2000, 0x3000 --> + </bitset> + + <reg32 offset="0xa81b" name="SP_VS_PROGRAM_COUNTER_OFFSET" type="uint" usage="rp_blit"/> + <reg64 offset="0xa81c" name="SP_VS_BASE" type="address" align="32" usage="rp_blit"/> <reg32 offset="0xa81e" name="SP_VS_PVT_MEM_PARAM" type="a6xx_sp_xs_pvt_mem_param" usage="rp_blit"/> - <reg64 offset="0xa81f" name="SP_VS_PVT_MEM_ADDR" type="waddress" align="32" usage="rp_blit"/> + <reg64 offset="0xa81f" name="SP_VS_PVT_MEM_BASE" type="waddress" align="32" usage="rp_blit"/> <reg32 offset="0xa821" name="SP_VS_PVT_MEM_SIZE" type="a6xx_sp_xs_pvt_mem_size" usage="rp_blit"/> - <reg32 offset="0xa822" name="SP_VS_TEX_COUNT" low="0" high="7" type="uint" usage="rp_blit"/> + <reg32 offset="0xa822" name="SP_VS_TSIZE" low="0" high="7" type="uint" usage="rp_blit"/> <reg32 offset="0xa823" name="SP_VS_CONFIG" type="a6xx_sp_xs_config" usage="rp_blit"/> - <reg32 offset="0xa824" name="SP_VS_INSTRLEN" low="0" high="27" type="uint" usage="rp_blit"/> - <reg32 offset="0xa825" name="SP_VS_PVT_MEM_HW_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_hw_stack_offset" usage="rp_blit"/> - <reg32 offset="0xa82d" name="SP_VS_VGPR_CONFIG" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xa824" name="SP_VS_INSTR_SIZE" low="0" high="27" type="uint" usage="rp_blit"/> + <reg32 offset="0xa825" name="SP_VS_PVT_MEM_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_stack_offset" usage="rp_blit"/> + <reg32 offset="0xa826" name="SP_VS_HYSTERESIS" type="a6xx_sp_xs_hysteresis" variants="A6XX-A7XX"/> + <reg32 offset="0xa826" name="SP_VS_HYSTERESIS" type="a8xx_sp_xs_hysteresis" variants="A8XX-"/> + <reg32 offset="0xa82d" name="SP_VS_VGS_CNTL" variants="A7XX-" usage="cmd"/> - <reg32 offset="0xa830" name="SP_HS_CTRL_REG0" type="a6xx_sp_xs_ctrl_reg0" usage="rp_blit"> + <reg32 offset="0xa830" name="SP_HS_CNTL_0" type="a6xx_sp_xs_cntl_0" usage="rp_blit"> <!-- There is no mergedregs bit, that comes from the VS. --> <bitfield name="EARLYPREAMBLE" pos="20" type="boolean"/> </reg32> @@ -4782,32 +3733,34 @@ to upconvert to 32b float internally? Total size of local storage in dwords divided by the wave size. The maximum value is 64. With the wave size being always 64 for HS, the maximum size of local storage should be: - 64 (wavesize) * 64 (SP_HS_WAVE_INPUT_SIZE) * 4 = 16k + 64 (wavesize) * 64 (SP_HS_CNTL_1) * 4 = 16k --> - <reg32 offset="0xa831" name="SP_HS_WAVE_INPUT_SIZE" low="0" high="7" type="uint" usage="rp_blit"/> - <reg32 offset="0xa832" name="SP_HS_BRANCH_COND" type="hex" usage="rp_blit"/> + <reg32 offset="0xa831" name="SP_HS_CNTL_1" low="0" high="7" type="uint" usage="rp_blit"/> + <reg32 offset="0xa832" name="SP_HS_BOOLEAN_CF_MASK" type="hex" usage="rp_blit"/> <!-- TODO: exact same layout as 0xa81b-0xa825 --> - <reg32 offset="0xa833" name="SP_HS_OBJ_FIRST_EXEC_OFFSET" type="uint" usage="rp_blit"/> - <reg64 offset="0xa834" name="SP_HS_OBJ_START" type="address" align="32" usage="rp_blit"/> + <reg32 offset="0xa833" name="SP_HS_PROGRAM_COUNTER_OFFSET" type="uint" usage="rp_blit"/> + <reg64 offset="0xa834" name="SP_HS_BASE" type="address" align="32" usage="rp_blit"/> <reg32 offset="0xa836" name="SP_HS_PVT_MEM_PARAM" type="a6xx_sp_xs_pvt_mem_param" usage="rp_blit"/> - <reg64 offset="0xa837" name="SP_HS_PVT_MEM_ADDR" type="waddress" align="32" usage="rp_blit"/> + <reg64 offset="0xa837" name="SP_HS_PVT_MEM_BASE" type="waddress" align="32" usage="rp_blit"/> <reg32 offset="0xa839" name="SP_HS_PVT_MEM_SIZE" type="a6xx_sp_xs_pvt_mem_size" usage="rp_blit"/> - <reg32 offset="0xa83a" name="SP_HS_TEX_COUNT" low="0" high="7" type="uint" usage="rp_blit"/> + <reg32 offset="0xa83a" name="SP_HS_TSIZE" low="0" high="7" type="uint" usage="rp_blit"/> <reg32 offset="0xa83b" name="SP_HS_CONFIG" type="a6xx_sp_xs_config" usage="rp_blit"/> - <reg32 offset="0xa83c" name="SP_HS_INSTRLEN" low="0" high="27" type="uint" usage="rp_blit"/> - <reg32 offset="0xa83d" name="SP_HS_PVT_MEM_HW_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_hw_stack_offset" usage="rp_blit"/> - <reg32 offset="0xa82f" name="SP_HS_VGPR_CONFIG" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xa83c" name="SP_HS_INSTR_SIZE" low="0" high="27" type="uint" usage="rp_blit"/> + <reg32 offset="0xa83d" name="SP_HS_PVT_MEM_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_stack_offset" usage="rp_blit"/> + <reg32 offset="0xa83e" name="SP_HS_HYSTERESIS" type="a6xx_sp_xs_hysteresis" variants="A6XX-A7XX"/> + <reg32 offset="0xa83e" name="SP_HS_HYSTERESIS" type="a8xx_sp_xs_hysteresis" variants="A8XX-"/> + <reg32 offset="0xa82f" name="SP_HS_VGS_CNTL" variants="A7XX-" usage="cmd"/> - <reg32 offset="0xa840" name="SP_DS_CTRL_REG0" type="a6xx_sp_xs_ctrl_reg0" usage="rp_blit"> + <reg32 offset="0xa840" name="SP_DS_CNTL_0" type="a6xx_sp_xs_cntl_0" usage="rp_blit"> <!-- There is no mergedregs bit, that comes from the VS. --> <bitfield name="EARLYPREAMBLE" pos="20" type="boolean"/> </reg32> - <reg32 offset="0xa841" name="SP_DS_BRANCH_COND" type="hex"/> + <reg32 offset="0xa841" name="SP_DS_BOOLEAN_CF_MASK" type="hex"/> <!-- TODO: exact same layout as 0xa802-0xa81a --> - <reg32 offset="0xa842" name="SP_DS_PRIMITIVE_CNTL" type="a6xx_sp_xs_prim_cntl" usage="rp_blit"/> - <array offset="0xa843" name="SP_DS_OUT" stride="1" length="16" usage="rp_blit"> + <reg32 offset="0xa842" name="SP_DS_OUTPUT_CNTL" type="a6xx_sp_xs_output_cntl" usage="rp_blit"/> + <array offset="0xa843" name="SP_DS_OUTPUT" stride="1" length="16" usage="rp_blit"> <reg32 offset="0x0" name="REG"> <bitfield name="A_REGID" low="0" high="7" type="a3xx_regid"/> <bitfield name="A_COMPMASK" low="8" high="11" type="hex"/> @@ -4815,7 +3768,7 @@ to upconvert to 32b float internally? <bitfield name="B_COMPMASK" low="24" high="27" type="hex"/> </reg32> </array> - <array offset="0xa853" name="SP_DS_VPC_DST" stride="1" length="8" usage="rp_blit"> + <array offset="0xa853" name="SP_DS_VPC_DEST" stride="1" length="8" usage="rp_blit"> <reg32 offset="0x0" name="REG"> <bitfield name="OUTLOC0" low="0" high="7" type="uint"/> <bitfield name="OUTLOC1" low="8" high="15" type="uint"/> @@ -4825,22 +3778,24 @@ to upconvert to 32b float internally? </array> <!-- TODO: exact same layout as 0xa81b-0xa825 --> - <reg32 offset="0xa85b" name="SP_DS_OBJ_FIRST_EXEC_OFFSET" type="uint" usage="rp_blit"/> - <reg64 offset="0xa85c" name="SP_DS_OBJ_START" type="address" align="32" usage="rp_blit"/> + <reg32 offset="0xa85b" name="SP_DS_PROGRAM_COUNTER_OFFSET" type="uint" usage="rp_blit"/> + <reg64 offset="0xa85c" name="SP_DS_BASE" type="address" align="32" usage="rp_blit"/> <reg32 offset="0xa85e" name="SP_DS_PVT_MEM_PARAM" type="a6xx_sp_xs_pvt_mem_param" usage="rp_blit"/> - <reg64 offset="0xa85f" name="SP_DS_PVT_MEM_ADDR" type="waddress" align="32" usage="rp_blit"/> + <reg64 offset="0xa85f" name="SP_DS_PVT_MEM_BASE" type="waddress" align="32" usage="rp_blit"/> <reg32 offset="0xa861" name="SP_DS_PVT_MEM_SIZE" type="a6xx_sp_xs_pvt_mem_size" usage="rp_blit"/> - <reg32 offset="0xa862" name="SP_DS_TEX_COUNT" low="0" high="7" type="uint" usage="rp_blit"/> + <reg32 offset="0xa862" name="SP_DS_TSIZE" low="0" high="7" type="uint" usage="rp_blit"/> <reg32 offset="0xa863" name="SP_DS_CONFIG" type="a6xx_sp_xs_config" usage="rp_blit"/> - <reg32 offset="0xa864" name="SP_DS_INSTRLEN" low="0" high="27" type="uint" usage="rp_blit"/> - <reg32 offset="0xa865" name="SP_DS_PVT_MEM_HW_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_hw_stack_offset" usage="rp_blit"/> - <reg32 offset="0xa868" name="SP_DS_VGPR_CONFIG" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xa864" name="SP_DS_INSTR_SIZE" low="0" high="27" type="uint" usage="rp_blit"/> + <reg32 offset="0xa865" name="SP_DS_PVT_MEM_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_stack_offset" usage="rp_blit"/> + <reg32 offset="0xa866" name="SP_DS_HYSTERESIS" type="a6xx_sp_xs_hysteresis" variants="A6XX-A7XX"/> + <reg32 offset="0xa866" name="SP_DS_HYSTERESIS" type="a8xx_sp_xs_hysteresis" variants="A8XX-"/> + <reg32 offset="0xa868" name="SP_DS_VGS_CNTL" variants="A7XX-" usage="cmd"/> - <reg32 offset="0xa870" name="SP_GS_CTRL_REG0" type="a6xx_sp_xs_ctrl_reg0" usage="rp_blit"> + <reg32 offset="0xa870" name="SP_GS_CNTL_0" type="a6xx_sp_xs_cntl_0" usage="rp_blit"> <!-- There is no mergedregs bit, that comes from the VS. --> <bitfield name="EARLYPREAMBLE" pos="20" type="boolean"/> </reg32> - <reg32 offset="0xa871" name="SP_GS_PRIM_SIZE" low="0" high="7" type="uint" usage="rp_blit"> + <reg32 offset="0xa871" name="SP_GS_CNTL_1" low="0" high="7" type="uint" usage="rp_blit"> <doc> Normally the size of the output of the last stage in dwords. It should be programmed as follows: @@ -4854,11 +3809,14 @@ to upconvert to 32b float internally? doesn't matter in practice. </doc> </reg32> - <reg32 offset="0xa872" name="SP_GS_BRANCH_COND" type="hex" usage="rp_blit"/> + <reg32 offset="0xa872" name="SP_GS_BOOLEAN_CF_MASK" type="hex" usage="rp_blit"/> <!-- TODO: exact same layout as 0xa802-0xa81a --> - <reg32 offset="0xa873" name="SP_GS_PRIMITIVE_CNTL" type="a6xx_sp_xs_prim_cntl" usage="rp_blit"/> - <array offset="0xa874" name="SP_GS_OUT" stride="1" length="16" usage="rp_blit"> + <reg32 offset="0xa873" name="SP_GS_OUTPUT_CNTL" type="a6xx_sp_xs_output_cntl" usage="rp_blit"> + <!-- FLAGS_REGID only for GS --> + <bitfield name="FLAGS_REGID" low="6" high="13" type="a3xx_regid"/> + </reg32> + <array offset="0xa874" name="SP_GS_OUTPUT" stride="1" length="16" usage="rp_blit"> <reg32 offset="0x0" name="REG"> <bitfield name="A_REGID" low="0" high="7" type="a3xx_regid"/> <bitfield name="A_COMPMASK" low="8" high="11" type="hex"/> @@ -4867,7 +3825,7 @@ to upconvert to 32b float internally? </reg32> </array> - <array offset="0xa884" name="SP_GS_VPC_DST" stride="1" length="8" usage="rp_blit"> + <array offset="0xa884" name="SP_GS_VPC_DEST" stride="1" length="8" usage="rp_blit"> <reg32 offset="0x0" name="REG"> <bitfield name="OUTLOC0" low="0" high="7" type="uint"/> <bitfield name="OUTLOC1" low="8" high="15" type="uint"/> @@ -4877,29 +3835,31 @@ to upconvert to 32b float internally? </array> <!-- TODO: exact same layout as 0xa81b-0xa825 --> - <reg32 offset="0xa88c" name="SP_GS_OBJ_FIRST_EXEC_OFFSET" type="uint" usage="rp_blit"/> - <reg64 offset="0xa88d" name="SP_GS_OBJ_START" type="address" align="32" usage="rp_blit"/> + <reg32 offset="0xa88c" name="SP_GS_PROGRAM_COUNTER_OFFSET" type="uint" usage="rp_blit"/> + <reg64 offset="0xa88d" name="SP_GS_BASE" type="address" align="32" usage="rp_blit"/> <reg32 offset="0xa88f" name="SP_GS_PVT_MEM_PARAM" type="a6xx_sp_xs_pvt_mem_param" usage="rp_blit"/> - <reg64 offset="0xa890" name="SP_GS_PVT_MEM_ADDR" type="waddress" align="32" usage="rp_blit"/> + <reg64 offset="0xa890" name="SP_GS_PVT_MEM_BASE" type="waddress" align="32" usage="rp_blit"/> <reg32 offset="0xa892" name="SP_GS_PVT_MEM_SIZE" type="a6xx_sp_xs_pvt_mem_size" usage="rp_blit"/> - <reg32 offset="0xa893" name="SP_GS_TEX_COUNT" low="0" high="7" type="uint" usage="rp_blit"/> + <reg32 offset="0xa893" name="SP_GS_TSIZE" low="0" high="7" type="uint" usage="rp_blit"/> <reg32 offset="0xa894" name="SP_GS_CONFIG" type="a6xx_sp_xs_config" usage="rp_blit"/> - <reg32 offset="0xa895" name="SP_GS_INSTRLEN" low="0" high="27" type="uint" usage="rp_blit"/> - <reg32 offset="0xa896" name="SP_GS_PVT_MEM_HW_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_hw_stack_offset" usage="rp_blit"/> - <reg32 offset="0xa899" name="SP_GS_VGPR_CONFIG" variants="A7XX-" usage="cmd"/> - - <reg64 offset="0xa8a0" name="SP_VS_TEX_SAMP" type="address" align="16" usage="cmd"/> - <reg64 offset="0xa8a2" name="SP_HS_TEX_SAMP" type="address" align="16" usage="cmd"/> - <reg64 offset="0xa8a4" name="SP_DS_TEX_SAMP" type="address" align="16" usage="cmd"/> - <reg64 offset="0xa8a6" name="SP_GS_TEX_SAMP" type="address" align="16" usage="cmd"/> - <reg64 offset="0xa8a8" name="SP_VS_TEX_CONST" type="address" align="64" usage="cmd"/> - <reg64 offset="0xa8aa" name="SP_HS_TEX_CONST" type="address" align="64" usage="cmd"/> - <reg64 offset="0xa8ac" name="SP_DS_TEX_CONST" type="address" align="64" usage="cmd"/> - <reg64 offset="0xa8ae" name="SP_GS_TEX_CONST" type="address" align="64" usage="cmd"/> + <reg32 offset="0xa895" name="SP_GS_INSTR_SIZE" low="0" high="27" type="uint" usage="rp_blit"/> + <reg32 offset="0xa896" name="SP_GS_PVT_MEM_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_stack_offset" usage="rp_blit"/> + <reg32 offset="0xa897" name="SP_GS_HYSTERESIS" type="a6xx_sp_xs_hysteresis" variants="A6XX-A7XX"/> + <reg32 offset="0xa897" name="SP_GS_HYSTERESIS" type="a8xx_sp_xs_hysteresis" variants="A8XX-"/> + <reg32 offset="0xa899" name="SP_GS_VGS_CNTL" variants="A7XX-" usage="cmd"/> + + <reg64 offset="0xa8a0" name="SP_VS_SAMPLER_BASE" type="address" align="16" usage="cmd"/> + <reg64 offset="0xa8a2" name="SP_HS_SAMPLER_BASE" type="address" align="16" usage="cmd"/> + <reg64 offset="0xa8a4" name="SP_DS_SAMPLER_BASE" type="address" align="16" usage="cmd"/> + <reg64 offset="0xa8a6" name="SP_GS_SAMPLER_BASE" type="address" align="16" usage="cmd"/> + <reg64 offset="0xa8a8" name="SP_VS_TEXMEMOBJ_BASE" type="address" align="64" usage="cmd"/> + <reg64 offset="0xa8aa" name="SP_HS_TEXMEMOBJ_BASE" type="address" align="64" usage="cmd"/> + <reg64 offset="0xa8ac" name="SP_DS_TEXMEMOBJ_BASE" type="address" align="64" usage="cmd"/> + <reg64 offset="0xa8ae" name="SP_GS_TEXMEMOBJ_BASE" type="address" align="64" usage="cmd"/> <!-- TODO: 4 unknown bool registers 0xa8c0-0xa8c3 --> - <reg32 offset="0xa980" name="SP_FS_CTRL_REG0" type="a6xx_sp_xs_ctrl_reg0" usage="rp_blit"> + <reg32 offset="0xa980" name="SP_PS_CNTL_0" type="a6xx_sp_xs_cntl_0" usage="rp_blit"> <bitfield name="THREADSIZE" pos="20" type="a6xx_threadsize"/> <bitfield name="UNK21" pos="21" type="boolean"/> <bitfield name="VARYING" pos="22" type="boolean"/> @@ -4909,8 +3869,7 @@ to upconvert to 32b float internally? fine derivatives and quad subgroup ops. </doc> </bitfield> - <!-- note: vk blob uses bit24 --> - <bitfield name="UNK24" pos="24" type="boolean"/> + <bitfield name="INOUTREGOVERLAP" pos="24" type="boolean"/> <bitfield name="UNK25" pos="25" type="boolean"/> <bitfield name="PIXLODENABLE" pos="26" type="boolean"> <doc> @@ -4923,20 +3882,26 @@ to upconvert to 32b float internally? <bitfield name="EARLYPREAMBLE" pos="28" type="boolean"/> <bitfield name="MERGEDREGS" pos="31" type="boolean"/> </reg32> - <reg32 offset="0xa981" name="SP_FS_BRANCH_COND" type="hex"/> - <reg32 offset="0xa982" name="SP_FS_OBJ_FIRST_EXEC_OFFSET" type="uint" usage="rp_blit"/> - <reg64 offset="0xa983" name="SP_FS_OBJ_START" type="address" align="32" usage="rp_blit"/> - <reg32 offset="0xa985" name="SP_FS_PVT_MEM_PARAM" type="a6xx_sp_xs_pvt_mem_param" usage="rp_blit"/> - <reg64 offset="0xa986" name="SP_FS_PVT_MEM_ADDR" type="waddress" align="32" usage="rp_blit"/> - <reg32 offset="0xa988" name="SP_FS_PVT_MEM_SIZE" type="a6xx_sp_xs_pvt_mem_size" usage="rp_blit"/> + <reg32 offset="0xa981" name="SP_PS_BOOLEAN_CF_MASK" type="hex"/> + <reg32 offset="0xa982" name="SP_PS_PROGRAM_COUNTER_OFFSET" type="uint" usage="rp_blit"/> + <reg64 offset="0xa983" name="SP_PS_BASE" type="address" align="32" usage="rp_blit"/> + <reg32 offset="0xa985" name="SP_PS_PVT_MEM_PARAM" type="a6xx_sp_xs_pvt_mem_param" usage="rp_blit"/> + <reg64 offset="0xa986" name="SP_PS_PVT_MEM_BASE" type="waddress" align="32" usage="rp_blit"/> + <reg32 offset="0xa988" name="SP_PS_PVT_MEM_SIZE" type="a6xx_sp_xs_pvt_mem_size" usage="rp_blit"/> - <reg32 offset="0xa989" name="SP_BLEND_CNTL" usage="rp_blit"> + <bitset name="a6xx_sp_blend_cntl" inline="yes"> <!-- per-mrt enable bit --> <bitfield name="ENABLE_BLEND" low="0" high="7"/> - <bitfield name="UNK8" pos="8" type="boolean"/> + <bitfield name="INDEPENDENT_BLEND_EN" pos="8" type="boolean"/> <bitfield name="DUAL_COLOR_IN_ENABLE" pos="9" type="boolean"/> <bitfield name="ALPHA_TO_COVERAGE" pos="10" type="boolean"/> + </bitset> + + <reg32 offset="0xa989" name="SP_BLEND_CNTL" type="a6xx_sp_blend_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0xa989" name="SP_BLEND_CNTL" type="a6xx_sp_blend_cntl" variants="A8XX-" usage="rp_blit"> + <bitfield name="ALPHA_TO_ONE" pos="11" type="boolean" variants="A8XX-"/> </reg32> + <reg32 offset="0xa98a" name="SP_SRGB_CNTL" usage="rp_blit"> <!-- Same as RB_SRGB_CNTL --> <bitfield name="SRGB_MRT0" pos="0" type="boolean"/> @@ -4948,7 +3913,7 @@ to upconvert to 32b float internally? <bitfield name="SRGB_MRT6" pos="6" type="boolean"/> <bitfield name="SRGB_MRT7" pos="7" type="boolean"/> </reg32> - <reg32 offset="0xa98b" name="SP_FS_RENDER_COMPONENTS" usage="rp_blit"> + <reg32 offset="0xa98b" name="SP_PS_OUTPUT_MASK" usage="rp_blit"> <bitfield name="RT0" low="0" high="3"/> <bitfield name="RT1" low="4" high="7"/> <bitfield name="RT2" low="8" high="11"/> @@ -4958,17 +3923,17 @@ to upconvert to 32b float internally? <bitfield name="RT6" low="24" high="27"/> <bitfield name="RT7" low="28" high="31"/> </reg32> - <reg32 offset="0xa98c" name="SP_FS_OUTPUT_CNTL0" usage="rp_blit"> + <reg32 offset="0xa98c" name="SP_PS_OUTPUT_CNTL" usage="rp_blit"> <bitfield name="DUAL_COLOR_IN_ENABLE" pos="0" type="boolean"/> <bitfield name="DEPTH_REGID" low="8" high="15" type="a3xx_regid"/> <bitfield name="SAMPMASK_REGID" low="16" high="23" type="a3xx_regid"/> <bitfield name="STENCILREF_REGID" low="24" high="31" type="a3xx_regid"/> </reg32> - <reg32 offset="0xa98d" name="SP_FS_OUTPUT_CNTL1" usage="rp_blit"> + <reg32 offset="0xa98d" name="SP_PS_MRT_CNTL" usage="rp_blit"> <bitfield name="MRT" low="0" high="3" type="uint"/> </reg32> - <array offset="0xa98e" name="SP_FS_OUTPUT" stride="1" length="8" usage="rp_blit"> + <array offset="0xa98e" name="SP_PS_OUTPUT" stride="1" length="8" usage="rp_blit"> <doc>per MRT</doc> <reg32 offset="0x0" name="REG"> <bitfield name="REGID" low="0" high="7" type="a3xx_regid"/> @@ -4976,7 +3941,7 @@ to upconvert to 32b float internally? </reg32> </array> - <array offset="0xa996" name="SP_FS_MRT" stride="1" length="8" usage="rp_blit"> + <array offset="0xa996" name="SP_PS_MRT" stride="1" length="8" usage="rp_blit"> <reg32 offset="0" name="REG"> <bitfield name="COLOR_FORMAT" low="0" high="7" type="a6xx_format"/> <bitfield name="COLOR_SINT" pos="8" type="boolean"/> @@ -4985,7 +3950,7 @@ to upconvert to 32b float internally? </reg32> </array> - <reg32 offset="0xa99e" name="SP_FS_PREFETCH_CNTL" usage="rp_blit"> + <reg32 offset="0xa99e" name="SP_PS_INITIAL_TEX_LOAD_CNTL" usage="rp_blit"> <bitfield name="COUNT" low="0" high="2" type="uint"/> <bitfield name="IJ_WRITE_DISABLE" pos="3" type="boolean"/> <doc> @@ -5002,7 +3967,7 @@ to upconvert to 32b float internally? <!-- Blob never uses it --> <bitfield name="CONSTSLOTID4COORD" low="16" high="24" type="uint" variants="A7XX-"/> </reg32> - <array offset="0xa99f" name="SP_FS_PREFETCH" stride="1" length="4" variants="A6XX" usage="rp_blit"> + <array offset="0xa99f" name="SP_PS_INITIAL_TEX_LOAD" stride="1" length="4" variants="A6XX" usage="rp_blit"> <reg32 offset="0" name="CMD" variants="A6XX"> <bitfield name="SRC" low="0" high="6" type="uint"/> <bitfield name="SAMP_ID" low="7" high="10" type="uint"/> @@ -5016,7 +3981,7 @@ to upconvert to 32b float internally? <bitfield name="CMD" low="29" high="31" type="a6xx_tex_prefetch_cmd"/> </reg32> </array> - <array offset="0xa99f" name="SP_FS_PREFETCH" stride="1" length="4" variants="A7XX-" usage="rp_blit"> + <array offset="0xa99f" name="SP_PS_INITIAL_TEX_LOAD" stride="1" length="4" variants="A7XX-" usage="rp_blit"> <reg32 offset="0" name="CMD" variants="A7XX-"> <bitfield name="SRC" low="0" high="6" type="uint"/> <bitfield name="SAMP_ID" low="7" high="9" type="uint"/> @@ -5028,22 +3993,21 @@ to upconvert to 32b float internally? <bitfield name="CMD" low="26" high="29" type="a6xx_tex_prefetch_cmd"/> </reg32> </array> - <array offset="0xa9a3" name="SP_FS_BINDLESS_PREFETCH" stride="1" length="4" usage="rp_blit"> + <array offset="0xa9a3" name="SP_PS_INITIAL_TEX_INDEX" stride="1" length="4" usage="rp_blit"> <reg32 offset="0" name="CMD"> <bitfield name="SAMP_ID" low="0" high="15" type="uint"/> <bitfield name="TEX_ID" low="16" high="31" type="uint"/> </reg32> </array> - <reg32 offset="0xa9a7" name="SP_FS_TEX_COUNT" low="0" high="7" type="uint" usage="rp_blit"/> + <reg32 offset="0xa9a7" name="SP_PS_TSIZE" low="0" high="7" type="uint" usage="rp_blit"/> <reg32 offset="0xa9a8" name="SP_UNKNOWN_A9A8" low="0" high="16" usage="cmd"/> <!-- always 0x0 ? --> - <reg32 offset="0xa9a9" name="SP_FS_PVT_MEM_HW_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_hw_stack_offset" usage="rp_blit"/> + <reg32 offset="0xa9a9" name="SP_PS_PVT_MEM_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_stack_offset" usage="rp_blit"/> + <reg32 offset="0xa9ab" name="SP_PS_HYSTERESIS" type="a6xx_sp_xs_hysteresis" variants="A6XX-A7XX"/> + <reg32 offset="0xa9ab" name="SP_PS_HYSTERESIS" type="a8xx_sp_xs_hysteresis" variants="A8XX-"/> <!-- TODO: unknown bool register at 0xa9aa, likely same as 0xa8c0-0xa8c3 but for FS --> - - - - <reg32 offset="0xa9b0" name="SP_CS_CTRL_REG0" type="a6xx_sp_xs_ctrl_reg0" usage="cmd"> + <reg32 offset="0xa9b0" name="SP_CS_CNTL_0" type="a6xx_sp_xs_cntl_0" usage="cmd"> <bitfield name="THREADSIZE" pos="20" type="a6xx_threadsize"/> <!-- seems to make SP use less concurrent threads when possible? --> <bitfield name="UNK21" pos="21" type="boolean"/> @@ -5053,8 +4017,15 @@ to upconvert to 32b float internally? <bitfield name="MERGEDREGS" pos="31" type="boolean"/> </reg32> + <enum name="a6xx_const_ram_mode"> + <value value="0x0" name="CONSTLEN_128"/> + <value value="0x1" name="CONSTLEN_192"/> + <value value="0x2" name="CONSTLEN_256"/> + <value value="0x3" name="CONSTLEN_512"/> <!-- a7xx only --> + </enum> + <!-- set for compute shaders --> - <reg32 offset="0xa9b1" name="SP_CS_UNKNOWN_A9B1" usage="cmd"> + <reg32 offset="0xa9b1" name="SP_CS_CNTL_1" usage="cmd"> <bitfield name="SHARED_SIZE" low="0" high="4" type="uint"> <doc> If 0 - all 32k of shared storage is enabled, otherwise @@ -5065,32 +4036,38 @@ to upconvert to 32b float internally? always return 0) </doc> </bitfield> - <bitfield name="UNK5" pos="5" type="boolean"/> - <!-- always 1 ? --> - <bitfield name="UNK6" pos="6" type="boolean"/> + <bitfield name="CONSTANTRAMMODE" low="5" high="6" type="a6xx_const_ram_mode"> + <doc> + This defines the split between consts and local + memory in the Local Buffer. The programmed value + must be at least the actual CONSTLEN. + </doc> + </bitfield> + <bitfield name="ALT_LM_ENCODE" pos="26" type="boolean"/> </reg32> - <reg32 offset="0xa9b2" name="SP_CS_BRANCH_COND" type="hex" usage="cmd"/> - <reg32 offset="0xa9b3" name="SP_CS_OBJ_FIRST_EXEC_OFFSET" type="uint" usage="cmd"/> - <reg64 offset="0xa9b4" name="SP_CS_OBJ_START" type="address" align="32" usage="cmd"/> + <reg32 offset="0xa9b2" name="SP_CS_BOOLEAN_CF_MASK" type="hex" usage="cmd"/> + <reg32 offset="0xa9b3" name="SP_CS_PROGRAM_COUNTER_OFFSET" type="uint" usage="cmd"/> + <reg64 offset="0xa9b4" name="SP_CS_BASE" type="address" align="32" usage="cmd"/> <reg32 offset="0xa9b6" name="SP_CS_PVT_MEM_PARAM" type="a6xx_sp_xs_pvt_mem_param" usage="cmd"/> - <reg64 offset="0xa9b7" name="SP_CS_PVT_MEM_ADDR" align="32" usage="cmd"/> + <reg64 offset="0xa9b7" name="SP_CS_PVT_MEM_BASE" type="waddress" align="32" usage="cmd"/> <reg32 offset="0xa9b9" name="SP_CS_PVT_MEM_SIZE" type="a6xx_sp_xs_pvt_mem_size" usage="cmd"/> - <reg32 offset="0xa9ba" name="SP_CS_TEX_COUNT" low="0" high="7" type="uint" usage="cmd"/> + <reg32 offset="0xa9ba" name="SP_CS_TSIZE" low="0" high="7" type="uint" usage="cmd"/> <reg32 offset="0xa9bb" name="SP_CS_CONFIG" type="a6xx_sp_xs_config" usage="cmd"/> - <reg32 offset="0xa9bc" name="SP_CS_INSTRLEN" low="0" high="27" type="uint" usage="cmd"/> - <reg32 offset="0xa9bd" name="SP_CS_PVT_MEM_HW_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_hw_stack_offset" usage="cmd"/> - <reg32 offset="0xa9be" name="SP_CS_UNKNOWN_A9BE" variants="A7XX-" usage="cmd"/> - <reg32 offset="0xa9c5" name="SP_CS_VGPR_CONFIG" variants="A7XX-" usage="cmd"/> - - <!-- new in a6xx gen4, matches HLSQ_CS_CNTL_0 --> - <reg32 offset="0xa9c2" name="SP_CS_CNTL_0" usage="cmd"> + <reg32 offset="0xa9bc" name="SP_CS_INSTR_SIZE" low="0" high="27" type="uint" usage="cmd"/> + <reg32 offset="0xa9bd" name="SP_CS_PVT_MEM_STACK_OFFSET" type="a6xx_sp_xs_pvt_mem_stack_offset" usage="cmd"/> + <reg32 offset="0xa9be" name="SP_CS_HYSTERESIS" type="a6xx_sp_xs_hysteresis" variants="A6XX-A7XX"/> + <reg32 offset="0xa9be" name="SP_CS_HYSTERESIS" type="a8xx_sp_xs_hysteresis" variants="A8XX-"/> + <reg32 offset="0xa9c5" name="SP_CS_VGS_CNTL" variants="A7XX-" usage="cmd"/> + + <!-- new in a6xx gen4, matches SP_CS_CONST_CONFIG_0 --> + <reg32 offset="0xa9c2" name="SP_CS_WIE_CNTL_0" usage="cmd"> <bitfield name="WGIDCONSTID" low="0" high="7" type="a3xx_regid"/> <bitfield name="WGSIZECONSTID" low="8" high="15" type="a3xx_regid"/> <bitfield name="WGOFFSETCONSTID" low="16" high="23" type="a3xx_regid"/> <bitfield name="LOCALIDREGID" low="24" high="31" type="a3xx_regid"/> </reg32> - <!-- new in a6xx gen4, matches HLSQ_CS_CNTL_1 --> - <reg32 offset="0xa9c3" name="SP_CS_CNTL_1" variants="A6XX" usage="cmd"> + <!-- new in a6xx gen4, matches SP_CS_WGE_CNTL --> + <reg32 offset="0xa9c3" name="SP_CS_WIE_CNTL_1" variants="A6XX" usage="cmd"> <!-- gl_LocalInvocationIndex --> <bitfield name="LINEARLOCALIDREGID" low="0" high="7" type="a3xx_regid"/> <!-- a650 has 6 "SP cores" (but 3 "SP"). this makes it use only @@ -5102,7 +4079,18 @@ to upconvert to 32b float internally? <bitfield name="THREADSIZE_SCALAR" pos="10" type="boolean"/> </reg32> - <reg32 offset="0xa9c3" name="SP_CS_CNTL_1" variants="A7XX-" usage="cmd"> + <enum name="a7xx_workitem_rast_order"> + <value value="0x0" name="WORKITEMRASTORDER_LINEAR"/> + <doc> + This is a fixed tiling, with 4x4 invocation outer tiles + containing 2x2 invocation inner tiles. The intent is to + improve cache locality with textures and images accessed + using gl_LocalInvocationID. + </doc> + <value value="0x1" name="WORKITEMRASTORDER_TILED"/> + </enum> + + <reg32 offset="0xa9c3" name="SP_CS_WIE_CNTL_1" variants="A7XX-" usage="cmd"> <!-- gl_LocalInvocationIndex --> <bitfield name="LINEARLOCALIDREGID" low="0" high="7" type="a3xx_regid"/> <!-- Must match SP_CS_CTRL --> @@ -5110,18 +4098,16 @@ to upconvert to 32b float internally? <!-- 1 thread per wave (would hang if THREAD128 is also set) --> <bitfield name="THREADSIZE_SCALAR" pos="9" type="boolean"/> - <!-- Affects getone. If enabled, getone sometimes executed 1? less times - than there are subgroups. - --> - <bitfield name="UNK15" pos="15" type="boolean"/> + <doc>How invocations/fibers within a workgroup are tiled.</doc> + <bitfield name="WORKITEMRASTORDER" pos="15" type="a7xx_workitem_rast_order"/> </reg32> <!-- TODO: two 64kb aligned addresses at a9d0/a9d2 --> - <reg64 offset="0xa9e0" name="SP_FS_TEX_SAMP" type="address" align="16" usage="rp_blit"/> - <reg64 offset="0xa9e2" name="SP_CS_TEX_SAMP" type="address" align="16" usage="cmd"/> - <reg64 offset="0xa9e4" name="SP_FS_TEX_CONST" type="address" align="64" usage="rp_blit"/> - <reg64 offset="0xa9e6" name="SP_CS_TEX_CONST" type="address" align="64" usage="cmd"/> + <reg64 offset="0xa9e0" name="SP_PS_SAMPLER_BASE" type="address" align="16" usage="rp_blit"/> + <reg64 offset="0xa9e2" name="SP_CS_SAMPLER_BASE" type="address" align="16" usage="cmd"/> + <reg64 offset="0xa9e4" name="SP_PS_TEXMEMOBJ_BASE" type="address" align="64" usage="rp_blit"/> + <reg64 offset="0xa9e6" name="SP_CS_TEXMEMOBJ_BASE" type="address" align="64" usage="cmd"/> <enum name="a6xx_bindless_descriptor_size"> <doc> @@ -5146,18 +4132,19 @@ to upconvert to 32b float internally? </array> <!-- - IBO state for compute shader: + UAV state for compute shader: --> - <reg64 offset="0xa9f2" name="SP_CS_IBO" type="address" align="16"/> - <reg32 offset="0xaa00" name="SP_CS_IBO_COUNT" low="0" high="6" type="uint"/> + <reg64 offset="0xa9f2" name="SP_CS_UAV_BASE" type="address" align="16" variants="A6XX"/> + <reg64 offset="0xa9f8" name="SP_CS_UAV_BASE" type="address" align="16" variants="A7XX-"/> + <reg32 offset="0xaa00" name="SP_CS_USIZE" low="0" high="6" type="uint"/> <!-- Correlated with avgs/uvgs usage in FS --> - <reg32 offset="0xaa01" name="SP_FS_VGPR_CONFIG" type="uint" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xaa01" name="SP_PS_VGS_CNTL" type="uint" variants="A7XX-" usage="cmd"/> - <reg32 offset="0xaa02" name="SP_PS_ALIASED_COMPONENTS_CONTROL" variants="A7XX-" usage="cmd"> + <reg32 offset="0xaa02" name="SP_PS_OUTPUT_CONST_CNTL" variants="A7XX-" usage="cmd"> <bitfield name="ENABLED" pos="0" type="boolean"/> </reg32> - <reg32 offset="0xaa03" name="SP_PS_ALIASED_COMPONENTS" variants="A7XX-" usage="cmd"> + <reg32 offset="0xaa03" name="SP_PS_OUTPUT_CONST_MASK" variants="A7XX-" usage="cmd"> <doc> Specify for which components the output color should be read from alias, e.g. for: @@ -5167,7 +4154,7 @@ to upconvert to 32b float internally? alias.1.b32.0 r1.x, c4.x alias.1.b32.0 r0.x, c0.x - the SP_PS_ALIASED_COMPONENTS would be 0x00001111 + the SP_PS_OUTPUT_CONST_MASK would be 0x00001111 </doc> <bitfield name="RT0" low="0" high="3"/> @@ -5180,6 +4167,18 @@ to upconvert to 32b float internally? <bitfield name="RT7" low="28" high="31"/> </reg32> + <array offset="0xaa04" name="SP_MRT_BLEND_CNTL" stride="1" length="8" variants="A8XX-"> + <reg32 offset="0" name="REG"> + <bitfield name="COLOR_BLEND_EN" pos="0" type="boolean"/> + <bitfield name="ALPHA_BLEND_EN" pos="1" type="boolean"/> + <bitfield name="COMPONENT_WRITE_MASK" low="7" high="10"/> + </reg32> + </array> + + <reg32 offset="0xaa0c" name="SP_ALPHA_TEST_CNTL" variants="A8XX-"> + <bitfield name="ALPHA_TEST" pos="8" type="boolean"/> + </reg32> + <reg32 offset="0xaaf2" name="SP_UNKNOWN_AAF2" type="uint" usage="cmd"/> <!-- @@ -5193,7 +4192,7 @@ to upconvert to 32b float internally? <value value="0x2" name="ISAMMODE_GL"/> </enum> - <reg32 offset="0xab00" name="SP_MODE_CONTROL" usage="rp_blit"> + <reg32 offset="0xab00" name="SP_MODE_CNTL" usage="rp_blit"> <!-- When set, half register loads from the constant file will load a 32-bit value (so hc0.y loads the same value as c0.y) @@ -5204,22 +4203,26 @@ to upconvert to 32b float internally? --> <bitfield name="CONSTANT_DEMOTION_ENABLE" pos="0" type="boolean"/> <bitfield name="ISAMMODE" low="1" high="2" type="a6xx_isam_mode"/> - <bitfield name="SHARED_CONSTS_ENABLE" pos="3" type="boolean"/> <!-- see HLSQ_SHARED_CONSTS --> + <bitfield name="SHARED_CONSTS_ENABLE" pos="3" type="boolean"/> <!-- see SP_SHARED_CONSTANT --> </reg32> <reg32 offset="0xab01" name="SP_UNKNOWN_AB01" variants="A7XX-" usage="cmd"/> - <reg32 offset="0xab02" name="SP_UNKNOWN_AB02" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xab02" name="SP_HLSQ_MODE_CNTL" variants="A7XX-" usage="cmd"> + <bitfield name="SHARED_CONSTS_ENABLE" pos="0" type="boolean"/> <!-- see SP_SHARED_CONSTANT --> + </reg32> + + <reg32 offset="0xab04" name="SP_PS_CONFIG" type="a6xx_sp_xs_config" usage="rp_blit"/> + <reg32 offset="0xab05" name="SP_PS_INSTR_SIZE" low="0" high="27" type="uint" usage="rp_blit"/> - <reg32 offset="0xab04" name="SP_FS_CONFIG" type="a6xx_sp_xs_config" usage="rp_blit"/> - <reg32 offset="0xab05" name="SP_FS_INSTRLEN" low="0" high="27" type="uint" usage="rp_blit"/> + <reg32 offset="0xab06" name="SP_BIN_SIZE" type="a8xx_bin_size" variants="A8XX-" usage="rp_blit"/> - <array offset="0xab10" name="SP_BINDLESS_BASE" stride="2" length="5" variants="A6XX" usage="rp_blit"> + <array offset="0xab10" name="SP_GFX_BINDLESS_BASE" stride="2" length="5" variants="A6XX" usage="rp_blit"> <reg64 offset="0" name="DESCRIPTOR" variants="A6XX"> <bitfield name="DESC_SIZE" low="0" high="1" type="a6xx_bindless_descriptor_size"/> <bitfield name="ADDR" low="2" high="63" shr="2" type="address"/> </reg64> </array> - <array offset="0xab0a" name="SP_BINDLESS_BASE" stride="2" length="8" variants="A7XX-" usage="rp_blit"> + <array offset="0xab0a" name="SP_GFX_BINDLESS_BASE" stride="2" length="8" variants="A7XX-" usage="rp_blit"> <reg64 offset="0" name="DESCRIPTOR" variants="A7XX-"> <bitfield name="DESC_SIZE" low="0" high="1" type="a6xx_bindless_descriptor_size"/> <bitfield name="ADDR" low="2" high="63" shr="2" type="address"/> @@ -5227,18 +4230,26 @@ to upconvert to 32b float internally? </array> <!-- - Combined IBO state for 3d pipe, used for Image and SSBO write/atomic - instructions VS/HS/DS/GS/FS. See SP_CS_IBO_* for compute shaders. + Combined UAV state for 3d pipe, used for Image and SSBO write/atomic + instructions VS/HS/DS/GS/FS. See SP_CS_UAV_BASE_* for compute shaders. --> - <reg64 offset="0xab1a" name="SP_IBO" type="address" align="16" usage="cmd"/> - <reg32 offset="0xab20" name="SP_IBO_COUNT" low="0" high="6" type="uint" usage="cmd"/> + <reg64 offset="0xab1a" name="SP_GFX_UAV_BASE" type="address" align="16" usage="cmd"/> + <reg32 offset="0xab20" name="SP_GFX_USIZE" low="0" high="6" type="uint" variants="A6XX-A7XX" usage="cmd"/> + <reg32 offset="0xab09" name="SP_GFX_USIZE" low="0" high="6" type="uint" variants="A8XX-" usage="cmd"/> - <reg32 offset="0xab22" name="SP_UNKNOWN_AB22" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xab22" name="SP_UNKNOWN_AB22" variants="A7XX" usage="cmd"/> - <bitset name="a6xx_sp_2d_dst_format" inline="yes"> - <bitfield name="NORM" pos="0" type="boolean"/> - <bitfield name="SINT" pos="1" type="boolean"/> - <bitfield name="UINT" pos="2" type="boolean"/> + <reg32 offset="0xab23" name="SP_UNKNOWN_AB23" variants="A8XX-"/> + + <enum name="a6xx_sp_a2d_output_ifmt_type"> + <value name="OUTPUT_IFMT_2D_FLOAT" value="0"/> + <value name="OUTPUT_IFMT_2D_SINT" value="1"/> + <value name="OUTPUT_IFMT_2D_UINT" value="2"/> + </enum> + + <bitset name="a6xx_sp_a2d_output_info" inline="yes"> + <bitfield name="HALF_PRECISION" pos="0" type="boolean"/> + <bitfield name="IFMT_TYPE" low="1" high="2" type="a6xx_sp_a2d_output_ifmt_type"/> <!-- looks like HW only cares about the base type of this format, which matches the ifmt? --> <bitfield name="COLOR_FORMAT" low="3" high="10" type="a6xx_format"/> @@ -5248,25 +4259,30 @@ to upconvert to 32b float internally? <bitfield name="MASK" low="12" high="15"/> </bitset> - <reg32 offset="0xacc0" name="SP_2D_DST_FORMAT" type="a6xx_sp_2d_dst_format" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xa9bf" name="SP_2D_DST_FORMAT" type="a6xx_sp_2d_dst_format" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xacc0" name="SP_A2D_OUTPUT_INFO" type="a6xx_sp_a2d_output_info" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xa9bf" name="SP_A2D_OUTPUT_INFO" type="a6xx_sp_a2d_output_info" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xae00" name="SP_DBG_ECO_CNTL" usage="cmd"/> - <reg32 offset="0xae01" name="SP_ADDR_MODE_CNTL" pos="0" type="a5xx_address_mode"/> + <reg32 offset="0xae00" name="SP_DBG_ECO_CNTL" usage="init"/> + <reg32 offset="0xae01" name="SP_ADDR_MODE_CNTL" pos="0" type="a5xx_address_mode" variants="A6XX"/> + <reg32 offset="0xae01" name="SP_SHADER_PROFILING" variants="A8XX-"/> <reg32 offset="0xae02" name="SP_NC_MODE_CNTL"> <!-- TODO: valid bits 0x3c3f, see kernel --> </reg32> - <reg32 offset="0xae03" name="SP_CHICKEN_BITS" usage="cmd"/> - <reg32 offset="0xae04" name="SP_FLOAT_CNTL" usage="cmd"> + <reg32 offset="0xae03" name="SP_CHICKEN_BITS" usage="init"/> + <reg32 offset="0xae04" name="SP_NC_MODE_CNTL_2" usage="init"> <bitfield name="F16_NO_INF" pos="3" type="boolean"/> </reg32> - <reg32 offset="0xae06" name="SP_UNKNOWN_AE06" variants="A7XX-" usage="cmd"/> - <reg32 offset="0xae08" name="SP_UNKNOWN_AE08" variants="A7XX-" usage="cmd"/> - <reg32 offset="0xae09" name="SP_UNKNOWN_AE09" variants="A7XX-" usage="cmd"/> - <reg32 offset="0xae0a" name="SP_UNKNOWN_AE0A" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xae05" name="SP_SS_CHICKEN_BITS_0" variants="A8XX-"/> + <reg32 offset="0xae06" name="SP_ISDB_CNTL" variants="A7XX-" usage="init"/> + <reg32 offset="0xae07" name="SP_PERFCTR_CNTL"/> + <reg32 offset="0xae08" name="SP_CHICKEN_BITS_1" variants="A7XX-" usage="init"/> + <reg32 offset="0xae09" name="SP_CHICKEN_BITS_2" variants="A7XX-" usage="init"/> + <reg32 offset="0xae0a" name="SP_CHICKEN_BITS_3" variants="A7XX-" usage="init"/> + <reg32 offset="0xae0b" name="SP_CHICKEN_BITS_4" variants="A8XX-"/> + <reg32 offset="0xae0c" name="SP_STATUS"/> - <reg32 offset="0xae0f" name="SP_PERFCTR_ENABLE" usage="cmd"> + <reg32 offset="0xae0f" name="SP_PERFCTR_SHADER_MASK" usage="init"> <!-- some perfcntrs are affected by a per-stage enable bit (PERF_SP_ALU_WORKING_CYCLES for example) TODO: verify position of HS/DS/GS bits --> @@ -5277,57 +4293,100 @@ to upconvert to 32b float internally? <bitfield name="FS" pos="4" type="boolean"/> <bitfield name="CS" pos="5" type="boolean"/> </reg32> - <array offset="0xae10" name="SP_PERFCTR_SP_SEL" stride="1" length="24"/> + <array offset="0xae10" name="SP_PERFCTR_SP_SEL" stride="1" length="24" variants="A6XX"/> <array offset="0xae60" name="SP_PERFCTR_HLSQ_SEL" stride="1" length="6" variants="A7XX-"/> - <reg32 offset="0xae6a" name="SP_UNKNOWN_AE6A" variants="A7XX-" usage="cmd"/> - <reg32 offset="0xae6b" name="SP_UNKNOWN_AE6B" variants="A7XX-" usage="cmd"/> - <reg32 offset="0xae6c" name="SP_UNKNOWN_AE6C" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xae6a" name="SP_UNKNOWN_AE6A" variants="A7XX-" usage="init"/> + <reg32 offset="0xae6b" name="SP_HLSQ_TIMEOUT_THRESHOLD_DP" variants="A7XX-" usage="init"/> + <reg32 offset="0xae6c" name="SP_HLSQ_DBG_ECO_CNTL" variants="A7XX-" usage="init"/> <reg32 offset="0xae6d" name="SP_READ_SEL" variants="A7XX-"> - <bitfield name="LOCATION" low="18" high="19" type="a7xx_state_location"/> - <bitfield name="PIPE" low="16" high="17" type="a7xx_pipe"/> + <bitfield name="CONTEXT" low="26" high="30"/> + <bitfield name="SLICE" low="21" high="25"/> + <bitfield name="LOCATION" low="18" high="20" type="a7xx_state_location"/> + <bitfield name="PIPE" low="16" high="17" type="adreno_pipe"/> <bitfield name="STATETYPE" low="8" high="15" type="a7xx_statetype_id"/> <bitfield name="USPTP" low="4" high="7"/> <bitfield name="SPTP" low="0" high="3"/> </reg32> <reg32 offset="0xae71" name="SP_DBG_CNTL" variants="A7XX-"/> - <reg32 offset="0xae73" name="SP_UNKNOWN_AE73" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xae73" name="SP_HLSQ_DBG_ECO_CNTL_1" variants="A7XX-"/> + <reg32 offset="0xae74" name="SP_HLSQ_DBG_ECO_CNTL_2" variants="A7XX-"/> + <reg32 offset="0xae76" name="SP_HLSQ_DBG_ECO_CNTL_3" variants="A8XX-"/> <array offset="0xae80" name="SP_PERFCTR_SP_SEL" stride="1" length="36" variants="A7XX-"/> <!-- TODO: there are 4 more percntr select registers (0xae28-0xae2b) --> <!-- TODO: there are a few unknown registers in the 0xae30-0xae52 range --> - <reg32 offset="0xbe22" name="SP_CONTEXT_SWITCH_GFX_PREEMPTION_SAFE_MODE"/> + <reg32 offset="0xae52" name="SP_CONTEXT_SWITCH_GFX_PREEMPTION_SAFE_MODE"/> + + <reg64 offset="0xae10" name="SP_HLSQ_GC_GMEM_RANGE_MIN" variants="A8XX-"/> + <reg64 offset="0xae12" name="SP_HLSQ_LPAC_GMEM_RANGE_MIN" variants="A8XX-"/> + <reg32 offset="0xae15" name="SP_LPAC_CPI_STATUS" variants="A8XX-"/> + <reg32 offset="0xae16" name="SP_LPAC_DBG_STATUS" variants="A8XX-"/> + <reg32 offset="0xae17" name="SP_LPAC_ISDB_BATCH_COUNT" variants="A8XX-"/> + <reg32 offset="0xae18" name="SP_LPAC_ISDB_BATCH_COUNT_INCR_EN" variants="A8XX-"/> + <reg32 offset="0xae19" name="SP_LPAC_ISDB_BATCH_COUNT_SHADERS" variants="A8XX-"/> + <reg32 offset="0xae30" name="SP_ISDB_BATCH_COUNT" variants="A7XX-"/> + <reg32 offset="0xae31" name="SP_ISDB_BATCH_COUNT_INCR_EN" variants="A7XX-"/> + <reg32 offset="0xae32" name="SP_ISDB_BATCH_COUNT_SHADERS" variants="A7XX-"/> + <reg32 offset="0xae35" name="SP_ISDB_DEBUG_CONFIG" variants="A7XX-"/> + + <reg32 offset="0xae3a" name="SP_SELF_THROTTLE_CONTROL" variants="A7XX-"/> + <reg32 offset="0xae3b" name="SP_DISPATCH_CNTL" variants="A7XX-"/> + <reg64 offset="0xae3c" name="SP_SW_DEBUG_ADDR" variants="A7XX-"/> + <reg64 offset="0xae3e" name="SP_ISDB_DEBUG_ADDR" variants="A7XX-"/> + + <array offset="0xaec0" name="SP_PERFCTR_HLSQ_SEL_2_0" stride="1" length="6" variants="A7XX-"/> <!-- The downstream kernel calls the debug cluster of registers "a6xx_sp_ps_tp_cluster" but this actually specifies the border color base for compute shaders. --> - <reg64 offset="0xb180" name="SP_PS_TP_BORDER_COLOR_BASE_ADDR" type="address" align="128" usage="cmd"/> - <reg32 offset="0xb182" name="SP_UNKNOWN_B182" low="0" high="2" usage="cmd"/> - <reg32 offset="0xb183" name="SP_UNKNOWN_B183" low="0" high="23" usage="cmd"/> + <reg64 offset="0xb180" name="TPL1_CS_BORDER_COLOR_BASE" type="address" align="128" usage="cmd"/> + <reg32 offset="0xb182" name="TPL1_PS_ROTATION_CNTL" low="0" high="2" usage="cmd"/> + <reg32 offset="0xb183" name="TPL1_PS_SWIZZLE_CNTL" low="0" high="23" usage="cmd"/> <reg32 offset="0xb190" name="SP_UNKNOWN_B190"/> <reg32 offset="0xb191" name="SP_UNKNOWN_B191"/> - <!-- could be all the stuff below here is actually TPL1?? --> + <reg32 offset="0xb2d6" name="TPL1_A2D_BIN_SIZE" type="a8xx_bin_size" variants="A8XX-" usage="rp_blit"/> + <reg32 offset="0xb2d7" name="TPL1_A2D_FILTER_CNTL" variants="A8XX-" usage="rp_blit"/> - <reg32 offset="0xb300" name="SP_TP_RAS_MSAA_CNTL" usage="rp_blit"> + <reg32 offset="0xb300" name="TPL1_RAS_MSAA_CNTL" usage="rp_blit"> <bitfield name="SAMPLES" low="0" high="1" type="a3xx_msaa_samples"/> <bitfield name="UNK2" low="2" high="3"/> </reg32> - <reg32 offset="0xb301" name="SP_TP_DEST_MSAA_CNTL" usage="rp_blit"> + <reg32 offset="0xb301" name="TPL1_DEST_MSAA_CNTL" usage="rp_blit"> <bitfield name="SAMPLES" low="0" high="1" type="a3xx_msaa_samples"/> <bitfield name="MSAA_DISABLE" pos="2" type="boolean"/> </reg32> <!-- looks to work in the same way as a5xx: --> - <reg64 offset="0xb302" name="SP_TP_BORDER_COLOR_BASE_ADDR" type="address" align="128" usage="cmd"/> - <reg32 offset="0xb304" name="SP_TP_SAMPLE_CONFIG" type="a6xx_sample_config" usage="rp_blit"/> - <reg32 offset="0xb305" name="SP_TP_SAMPLE_LOCATION_0" type="a6xx_sample_locations" usage="rp_blit"/> - <reg32 offset="0xb306" name="SP_TP_SAMPLE_LOCATION_1" type="a6xx_sample_locations" usage="rp_blit"/> - <reg32 offset="0xb307" name="SP_TP_WINDOW_OFFSET" type="a6xx_reg_xy" usage="rp_blit"/> - <reg32 offset="0xb309" name="SP_TP_MODE_CNTL" usage="cmd"> + <reg64 offset="0xb302" name="TPL1_GFX_BORDER_COLOR_BASE" type="address" align="128" usage="cmd"/> + <reg32 offset="0xb304" name="TPL1_MSAA_SAMPLE_POS_CNTL" type="a6xx_msaa_sample_pos_cntl" variants="A6XX-A7XX" usage="rp_blit"/> + <reg32 offset="0xb305" name="TPL1_PROGRAMMABLE_MSAA_POS_0" type="a6xx_programmable_msaa_pos" usage="rp_blit" variants="A6XX-A7XX" /> + <reg32 offset="0xb306" name="TPL1_PROGRAMMABLE_MSAA_POS_1" type="a6xx_programmable_msaa_pos" usage="rp_blit" variants="A6XX-A7XX" /> + <reg32 offset="0xb307" name="TPL1_WINDOW_OFFSET" type="a6xx_reg_xy" usage="rp_blit"/> + + <reg32 offset="0xb304" name="TPL1_BIN_SIZE" type="a8xx_bin_size" variants="A8XX-" usage="rp_blit"/> + + <enum name="a6xx_coord_round"> + <value value="0" name="COORD_TRUNCATE"/> + <value value="1" name="COORD_ROUND_NEAREST_EVEN"/> + </enum> + + <enum name="a6xx_nearest_mode"> + <value value="0" name="ROUND_CLAMP_TRUNCATE"/> + <value value="1" name="CLAMP_ROUND_TRUNCATE"/> + <value value="2" name="ROUND_FLOAT_TO_INT"/> <!-- only ARRAYCOORDROUNDMODE --> + </enum> + + <reg32 offset="0xb309" name="TPL1_MODE_CNTL" usage="cmd"> <bitfield name="ISAMMODE" low="0" high="1" type="a6xx_isam_mode"/> - <bitfield name="UNK3" low="2" high="7"/> + <bitfield name="TEXCOORDROUNDMODE" pos="2" type="a6xx_coord_round"/> + <bitfield name="ARRAYCOORDROUNDMODE" low="3" high="4" type="a6xx_coord_round"/> + <bitfield name="NEARESTMIPSNAP" pos="5" type="a6xx_nearest_mode"/> + <bitfield name="SAMPLEREPLICATE" pos="6" type="boolean"/> + <bitfield name="DESTDATATYPEOVERRIDE" pos="7" type="boolean"/> + <bitfield name="PACK_SAMP_REDUCED_PRECISION" pos="8" type="boolean"/> </reg32> <reg32 offset="0xb310" name="SP_UNKNOWN_B310" variants="A7XX-" usage="cmd"/> @@ -5336,42 +4395,45 @@ to upconvert to 32b float internally? badly named or the functionality moved in a6xx. But downstream kernel calls this "a6xx_sp_ps_tp_2d_cluster" --> - <reg32 offset="0xb4c0" name="SP_PS_2D_SRC_INFO" type="a6xx_2d_src_surf_info" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xb4c1" name="SP_PS_2D_SRC_SIZE" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb4c0" name="TPL1_A2D_SRC_TEXTURE_INFO" type="a6xx_a2d_src_texture_info" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb4c1" name="TPL1_A2D_SRC_TEXTURE_SIZE" variants="A6XX" usage="rp_blit"> <bitfield name="WIDTH" low="0" high="14" type="uint"/> <bitfield name="HEIGHT" low="15" high="29" type="uint"/> </reg32> - <reg64 offset="0xb4c2" name="SP_PS_2D_SRC" type="address" align="16" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xb4c4" name="SP_PS_2D_SRC_PITCH" variants="A6XX" usage="rp_blit"> + <reg64 offset="0xb4c2" name="TPL1_A2D_SRC_TEXTURE_BASE" type="address" align="16" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb4c4" name="TPL1_A2D_SRC_TEXTURE_PITCH" variants="A6XX" usage="rp_blit"> <bitfield name="UNK0" low="0" high="8"/> <bitfield name="PITCH" low="9" high="23" shr="6" type="uint"/> </reg32> - <reg32 offset="0xb2c0" name="SP_PS_2D_SRC_INFO" type="a6xx_2d_src_surf_info" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xb2c1" name="SP_PS_2D_SRC_SIZE" variants="A7XX"> + <reg32 offset="0xb2c0" name="TPL1_A2D_SRC_TEXTURE_INFO" type="a6xx_a2d_src_texture_info" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xb2c1" name="TPL1_A2D_SRC_TEXTURE_SIZE" variants="A7XX-"> <bitfield name="WIDTH" low="0" high="14" type="uint"/> <bitfield name="HEIGHT" low="15" high="29" type="uint"/> </reg32> - <reg64 offset="0xb2c2" name="SP_PS_2D_SRC" type="address" align="16" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xb2c4" name="SP_PS_2D_SRC_PITCH" variants="A7XX"> - <bitfield name="UNK0" low="0" high="8"/> - <bitfield name="PITCH" low="9" high="23" shr="6" type="uint"/> + <reg64 offset="0xb2c2" name="TPL1_A2D_SRC_TEXTURE_BASE" type="address" align="16" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xb2c4" name="TPL1_A2D_SRC_TEXTURE_PITCH" variants="A7XX-"> + <!-- + Bits from 3..9 must be zero unless 'TPL1_A2D_BLT_CNTL::TYPE' + is A6XX_TEX_IMG_BUFFER, which allows for lower alignment. + --> + <bitfield name="PITCH" low="3" high="23" type="uint"/> </reg32> <!-- planes for NV12, etc. (TODO: not tested) --> - <reg64 offset="0xb4c5" name="SP_PS_2D_SRC_PLANE1" type="address" align="16" variants="A6XX"/> - <reg32 offset="0xb4c7" name="SP_PS_2D_SRC_PLANE_PITCH" low="0" high="11" shr="6" type="uint" variants="A6XX"/> - <reg64 offset="0xb4c8" name="SP_PS_2D_SRC_PLANE2" type="address" align="16" variants="A6XX"/> + <reg64 offset="0xb4c5" name="TPL1_A2D_SRC_TEXTURE_BASE_1" type="address" align="16" variants="A6XX"/> + <reg32 offset="0xb4c7" name="TPL1_A2D_SRC_TEXTURE_PITCH_1" low="0" high="11" shr="6" type="uint" variants="A6XX"/> + <reg64 offset="0xb4c8" name="TPL1_A2D_SRC_TEXTURE_BASE_2" type="address" align="16" variants="A6XX"/> - <reg64 offset="0xb2c5" name="SP_PS_2D_SRC_PLANE1" type="address" align="16" variants="A7XX-"/> - <reg32 offset="0xb2c7" name="SP_PS_2D_SRC_PLANE_PITCH" low="0" high="11" shr="6" type="uint" variants="A7XX-"/> - <reg64 offset="0xb2c8" name="SP_PS_2D_SRC_PLANE2" type="address" align="16" variants="A7XX-"/> + <reg64 offset="0xb2c5" name="TPL1_A2D_SRC_TEXTURE_BASE_1" type="address" align="16" variants="A7XX-"/> + <reg32 offset="0xb2c7" name="TPL1_A2D_SRC_TEXTURE_PITCH_1" low="0" high="11" shr="6" type="uint" variants="A7XX-"/> + <reg64 offset="0xb2c8" name="TPL1_A2D_SRC_TEXTURE_BASE_2" type="address" align="16" variants="A7XX-"/> - <reg64 offset="0xb4ca" name="SP_PS_2D_SRC_FLAGS" type="address" align="16" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xb4cc" name="SP_PS_2D_SRC_FLAGS_PITCH" low="0" high="7" shr="6" type="uint" variants="A6XX" usage="rp_blit"/> + <reg64 offset="0xb4ca" name="TPL1_A2D_SRC_TEXTURE_FLAG_BASE" type="address" align="16" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb4cc" name="TPL1_A2D_SRC_TEXTURE_FLAG_PITCH" low="0" high="7" shr="6" type="uint" variants="A6XX" usage="rp_blit"/> - <reg64 offset="0xb2ca" name="SP_PS_2D_SRC_FLAGS" type="address" align="16" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xb2cc" name="SP_PS_2D_SRC_FLAGS_PITCH" low="0" high="7" shr="6" type="uint" variants="A7XX-" usage="rp_blit"/> + <reg64 offset="0xb2ca" name="TPL1_A2D_SRC_TEXTURE_FLAG_BASE" type="address" align="16" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xb2cc" name="TPL1_A2D_SRC_TEXTURE_FLAG_PITCH" low="0" high="7" shr="6" type="uint" variants="A7XX-" usage="rp_blit"/> <reg32 offset="0xb4cd" name="SP_PS_UNKNOWN_B4CD" low="6" high="31" variants="A6XX"/> <reg32 offset="0xb4ce" name="SP_PS_UNKNOWN_B4CE" low="0" high="31" variants="A6XX"/> @@ -5383,14 +4445,19 @@ to upconvert to 32b float internally? <reg32 offset="0xb2ce" name="SP_PS_UNKNOWN_B4CE" low="0" high="31" variants="A7XX"/> <reg32 offset="0xb2cf" name="SP_PS_UNKNOWN_B4CF" low="0" high="30" variants="A7XX"/> <reg32 offset="0xb2d0" name="SP_PS_UNKNOWN_B4D0" low="0" high="29" variants="A7XX"/> - <reg32 offset="0xb2d1" name="SP_PS_2D_WINDOW_OFFSET" type="a6xx_reg_xy" variants="A7XX"/> - <reg32 offset="0xb2d2" name="SP_PS_UNKNOWN_B2D2" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xab21" name="SP_WINDOW_OFFSET" type="a6xx_reg_xy" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xb2d1" name="TPL1_A2D_WINDOW_OFFSET" type="a6xx_reg_xy" variants="A7XX-"/> + <reg32 offset="0xb2d2" name="TPL1_A2D_BLT_CNTL" variants="A7XX-" usage="rp_blit"> + <bitfield name="RAW_COPY" pos="0" type="boolean"/> + <bitfield name="START_OFFSET_TEXELS" low="16" high="21"/> + <bitfield name="TYPE" low="29" high="31" type="a6xx_tex_type"/> + </reg32> + <reg32 offset="0xab21" name="SP_WINDOW_OFFSET" type="a6xx_reg_xy" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0xab07" name="SP_WINDOW_OFFSET" type="a6xx_reg_xy" variants="A8XX-" usage="rp_blit"/> <!-- always 0x100000 or 0x1000000? --> - <reg32 offset="0xb600" name="TPL1_DBG_ECO_CNTL" low="0" high="25" usage="cmd"/> - <reg32 offset="0xb601" name="TPL1_ADDR_MODE_CNTL" type="a5xx_address_mode"/> - <reg32 offset="0xb602" name="TPL1_DBG_ECO_CNTL1" usage="cmd"> + <reg32 offset="0xb600" name="TPL1_DBG_ECO_CNTL" low="0" high="25" usage="init"/> + <reg32 offset="0xb601" name="TPL1_ADDR_MODE_CNTL" type="a5xx_address_mode" variants="A6XX"/> + <reg32 offset="0xb602" name="TPL1_DBG_ECO_CNTL1" usage="init"> <!-- Affects UBWC in some way, if BLIT_OP_SCALE is done with this bit set and if other blit is done without it - UBWC image may be copied incorrectly. --> @@ -5403,58 +4470,67 @@ to upconvert to 32b float internally? <bitfield name="UPPER_BIT" pos="4" type="uint"/> <bitfield name="UNK6" low="6" high="7"/> </reg32> - <reg32 offset="0xb605" name="TPL1_UNKNOWN_B605" low="0" high="7" type="uint" variants="A6XX" usage="cmd"/> <!-- always 0x0 or 0x44 ? --> + <reg32 offset="0xb605" name="TPL1_UNKNOWN_B605" low="0" high="7" type="uint" variants="A6XX" usage="init"/> <!-- always 0x0 or 0x44 ? --> - <reg32 offset="0xb608" name="TPL1_BICUBIC_WEIGHTS_TABLE_0" low="0" high="29" variants="A6XX"/> - <reg32 offset="0xb609" name="TPL1_BICUBIC_WEIGHTS_TABLE_1" low="0" high="29" variants="A6XX"/> - <reg32 offset="0xb60a" name="TPL1_BICUBIC_WEIGHTS_TABLE_2" low="0" high="29" variants="A6XX"/> - <reg32 offset="0xb60b" name="TPL1_BICUBIC_WEIGHTS_TABLE_3" low="0" high="29" variants="A6XX"/> - <reg32 offset="0xb60c" name="TPL1_BICUBIC_WEIGHTS_TABLE_4" low="0" high="29" variants="A6XX"/> + <array offset="0xb608" name="TPL1_BICUBIC_WEIGHTS_TABLE" stride="1" length="5" variants="A6XX"> + <reg32 offset="0" name="REG" low="0" high="29"/> + </array> - <reg32 offset="0xb608" name="TPL1_BICUBIC_WEIGHTS_TABLE_0" low="0" high="29" variants="A7XX" usage="cmd"/> - <reg32 offset="0xb609" name="TPL1_BICUBIC_WEIGHTS_TABLE_1" low="0" high="29" variants="A7XX" usage="cmd"/> - <reg32 offset="0xb60a" name="TPL1_BICUBIC_WEIGHTS_TABLE_2" low="0" high="29" variants="A7XX" usage="cmd"/> - <reg32 offset="0xb60b" name="TPL1_BICUBIC_WEIGHTS_TABLE_3" low="0" high="29" variants="A7XX" usage="cmd"/> - <reg32 offset="0xb60c" name="TPL1_BICUBIC_WEIGHTS_TABLE_4" low="0" high="29" variants="A7XX" usage="cmd"/> + <array offset="0xb608" name="TPL1_BICUBIC_WEIGHTS_TABLE" stride="1" length="5" variants="A7XX"> + <reg32 offset="0" name="REG" low="0" high="29" usage="cmd"/> + </array> + + <array offset="0xb606" name="TPL1_BICUBIC_WEIGHTS_TABLE" stride="1" length="25" variants="A8XX"> + <reg32 offset="0" name="REG" low="0" high="29"/> + </array> <array offset="0xb610" name="TPL1_PERFCTR_TP_SEL" stride="1" length="12" variants="A6XX"/> <array offset="0xb610" name="TPL1_PERFCTR_TP_SEL" stride="1" length="18" variants="A7XX"/> + <array offset="0xb620" name="TPL1_PERFCTR_TP_SEL" stride="1" length="20" variants="A8XX"/> <!-- TODO: 4 more perfcntr sel at 0xb620 ? --> - <bitset name="a6xx_hlsq_xs_cntl" inline="yes"> + <bitset name="a6xx_xs_const_config" inline="yes"> <bitfield name="CONSTLEN" low="0" high="7" shr="2" type="uint"/> <bitfield name="ENABLED" pos="8" type="boolean"/> <bitfield name="READ_IMM_SHARED_CONSTS" pos="9" type="boolean" variants="A7XX-"/> </bitset> - <reg32 offset="0xb800" name="HLSQ_VS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xb801" name="HLSQ_HS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xb802" name="HLSQ_DS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xb803" name="HLSQ_GS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb800" name="SP_VS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb801" name="SP_HS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb802" name="SP_DS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb803" name="SP_GS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xa827" name="HLSQ_VS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xa83f" name="HLSQ_HS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xa867" name="HLSQ_DS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xa898" name="HLSQ_GS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xa827" name="SP_VS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xa83f" name="SP_HS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xa867" name="SP_DS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xa898" name="SP_GS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xa9aa" name="HLSQ_FS_UNKNOWN_A9AA" variants="A7XX-" usage="rp_blit"> - <!-- Tentatively named, appears to disable consts being loaded via CP_LOAD_STATE6_FRAG --> - <bitfield name="CONSTS_LOAD_DISABLE" pos="0" type="boolean"/> + <reg32 offset="0xa9aa" name="SP_RENDER_CNTL" variants="A7XX-" usage="rp_blit"> + <bitfield name="FS_DISABLE" pos="0" type="boolean"/> </reg32> - <!-- Always 0 --> - <reg32 offset="0xa9ac" name="HLSQ_UNKNOWN_A9AC" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xa9ac" name="SP_DITHER_CNTL" variants="A7XX-" usage="cmd"> + <bitfield name="DITHER_MODE_MRT0" low="0" high="1" type="adreno_rb_dither_mode"/> + <bitfield name="DITHER_MODE_MRT1" low="2" high="3" type="adreno_rb_dither_mode"/> + <bitfield name="DITHER_MODE_MRT2" low="4" high="5" type="adreno_rb_dither_mode"/> + <bitfield name="DITHER_MODE_MRT3" low="6" high="7" type="adreno_rb_dither_mode"/> + <bitfield name="DITHER_MODE_MRT4" low="8" high="9" type="adreno_rb_dither_mode"/> + <bitfield name="DITHER_MODE_MRT5" low="10" high="11" type="adreno_rb_dither_mode"/> + <bitfield name="DITHER_MODE_MRT6" low="12" high="13" type="adreno_rb_dither_mode"/> + <bitfield name="DITHER_MODE_MRT7" low="14" high="15" type="adreno_rb_dither_mode"/> + </reg32> - <!-- Used in VK_KHR_fragment_shading_rate --> - <reg32 offset="0xa9ad" name="HLSQ_UNKNOWN_A9AD" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xa9ad" name="SP_VRS_CONFIG" variants="A7XX-" usage="rp_blit"> + <bitfield name="PIPELINE_FSR_ENABLE" pos="0" type="boolean"/> + <bitfield name="ATTACHMENT_FSR_ENABLE" pos="1" type="boolean"/> + <bitfield name="PRIMITIVE_FSR_ENABLE" pos="3" type="boolean"/> + </reg32> - <reg32 offset="0xa9ae" name="HLSQ_UNKNOWN_A9AE" variants="A7XX-" usage="rp_blit"> + <reg32 offset="0xa9ae" name="SP_PS_CNTL_1" variants="A7XX-" usage="rp_blit"> <bitfield name="SYSVAL_REGS_COUNT" low="0" high="7" type="uint"/> - <!-- UNK8 is set on a730/a740 --> - <bitfield name="UNK8" pos="8" type="boolean"/> - <!-- UNK9 is set on a750 --> - <bitfield name="UNK9" pos="9" type="boolean"/> + <bitfield name="DEFER_WAVE_ALLOC_DIS" pos="8" type="boolean"/> + <bitfield name="EVICT_BUF_MODE" low="9" high="10"/> </reg32> <reg32 offset="0xb820" name="HLSQ_LOAD_STATE_GEOM_CMD"/> @@ -5462,94 +4538,97 @@ to upconvert to 32b float internally? <reg32 offset="0xb823" name="HLSQ_LOAD_STATE_GEOM_DATA"/> - <bitset name="a6xx_hlsq_fs_cntl_0" inline="yes"> + <bitset name="a6xx_sp_ps_wave_cntl" inline="yes"> <!-- must match SP_FS_CTRL --> <bitfield name="THREADSIZE" pos="0" type="a6xx_threadsize"/> <bitfield name="VARYINGS" pos="1" type="boolean"/> <bitfield name="UNK2" low="2" high="11"/> </bitset> - <bitset name="a6xx_hlsq_control_3_reg" inline="yes"> + <bitset name="a6xx_sp_reg_prog_id_1" inline="yes"> <!-- register loaded with position (bary.f) --> <bitfield name="IJ_PERSP_PIXEL" low="0" high="7" type="a3xx_regid"/> <bitfield name="IJ_LINEAR_PIXEL" low="8" high="15" type="a3xx_regid"/> <bitfield name="IJ_PERSP_CENTROID" low="16" high="23" type="a3xx_regid"/> <bitfield name="IJ_LINEAR_CENTROID" low="24" high="31" type="a3xx_regid"/> </bitset> - <bitset name="a6xx_hlsq_control_4_reg" inline="yes"> + <bitset name="a6xx_sp_reg_prog_id_2" inline="yes"> <bitfield name="IJ_PERSP_SAMPLE" low="0" high="7" type="a3xx_regid"/> <bitfield name="IJ_LINEAR_SAMPLE" low="8" high="15" type="a3xx_regid"/> <bitfield name="XYCOORDREGID" low="16" high="23" type="a3xx_regid"/> <bitfield name="ZWCOORDREGID" low="24" high="31" type="a3xx_regid"/> </bitset> - <bitset name="a6xx_hlsq_control_5_reg" inline="yes"> + <bitset name="a6xx_sp_reg_prog_id_3" inline="yes"> <bitfield name="LINELENGTHREGID" low="0" high="7" type="a3xx_regid"/> <bitfield name="FOVEATIONQUALITYREGID" low="8" high="15" type="a3xx_regid"/> </bitset> - <reg32 offset="0xb980" type="a6xx_hlsq_fs_cntl_0" name="HLSQ_FS_CNTL_0" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb980" type="a6xx_sp_ps_wave_cntl" name="SP_PS_WAVE_CNTL" variants="A6XX" usage="rp_blit"/> <reg32 offset="0xb981" name="HLSQ_UNKNOWN_B981" pos="0" type="boolean" variants="A6XX"/> <!-- never used by blob --> - <reg32 offset="0xb982" name="HLSQ_CONTROL_1_REG" low="0" high="2" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb982" name="SP_LB_PARAM_LIMIT" low="0" high="2" variants="A6XX" usage="rp_blit"> <!-- Sets the maximum number of primitives allowed in one FS wave minus one, similarly to the A3xx field, except that it's not necessary to set it to anything but the maximum, since the hardware will simply emit smaller waves when it runs out of space. --> <bitfield name="PRIMALLOCTHRESHOLD" low="0" high="2" type="uint"/> </reg32> - <reg32 offset="0xb983" name="HLSQ_CONTROL_2_REG" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb983" name="SP_REG_PROG_ID_0" variants="A6XX" usage="rp_blit"> <bitfield name="FACEREGID" low="0" high="7" type="a3xx_regid"/> <!-- SAMPLEID is loaded into a half-precision register: --> <bitfield name="SAMPLEID" low="8" high="15" type="a3xx_regid"/> <bitfield name="SAMPLEMASK" low="16" high="23" type="a3xx_regid"/> <bitfield name="CENTERRHW" low="24" high="31" type="a3xx_regid"/> </reg32> - <reg32 offset="0xb984" type="a6xx_hlsq_control_3_reg" name="HLSQ_CONTROL_3_REG" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xb985" type="a6xx_hlsq_control_4_reg" name="HLSQ_CONTROL_4_REG" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xb986" type="a6xx_hlsq_control_5_reg" name="HLSQ_CONTROL_5_REG" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xb987" name="HLSQ_CS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A6XX" usage="cmd"/> - <reg32 offset="0xa9c6" type="a6xx_hlsq_fs_cntl_0" name="HLSQ_FS_CNTL_0" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xa9c7" name="HLSQ_CONTROL_1_REG" low="0" high="2" variants="A7XX-" usage="rp_blit"> - <bitfield name="PRIMALLOCTHRESHOLD" low="0" high="2" type="uint"/> + <reg32 offset="0xb984" type="a6xx_sp_reg_prog_id_1" name="SP_REG_PROG_ID_1" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb985" type="a6xx_sp_reg_prog_id_2" name="SP_REG_PROG_ID_2" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb986" type="a6xx_sp_reg_prog_id_3" name="SP_REG_PROG_ID_3" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb987" name="SP_CS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A6XX" usage="cmd"/> + <reg32 offset="0xa9c6" type="a6xx_sp_ps_wave_cntl" name="SP_PS_WAVE_CNTL" variants="A7XX" usage="rp_blit"/> + <reg32 offset="0xa9c6" name="SP_PS_WAVE_CNTL" variants="A8XX-" usage="rp_blit"> + <bitfield name="VARYINGS" pos="1" type="boolean"/> + </reg32> + <reg32 offset="0xa9c7" name="SP_LB_PARAM_LIMIT" low="0" high="2" variants="A7XX-" usage="rp_blit"> + <bitfield name="PRIMALLOCTHRESHOLD" low="0" high="2" type="uint"/> </reg32> - <reg32 offset="0xa9c8" name="HLSQ_CONTROL_2_REG" variants="A7XX-" usage="rp_blit"> + <reg32 offset="0xa9c8" name="SP_REG_PROG_ID_0" variants="A7XX-" usage="rp_blit"> <bitfield name="FACEREGID" low="0" high="7" type="a3xx_regid"/> <!-- SAMPLEID is loaded into a half-precision register: --> <bitfield name="SAMPLEID" low="8" high="15" type="a3xx_regid"/> <bitfield name="SAMPLEMASK" low="16" high="23" type="a3xx_regid"/> <bitfield name="CENTERRHW" low="24" high="31" type="a3xx_regid"/> </reg32> - <reg32 offset="0xa9c9" type="a6xx_hlsq_control_3_reg" name="HLSQ_CONTROL_3_REG" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xa9ca" type="a6xx_hlsq_control_4_reg" name="HLSQ_CONTROL_4_REG" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xa9cb" type="a6xx_hlsq_control_5_reg" name="HLSQ_CONTROL_5_REG" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xa9cd" name="HLSQ_CS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A7XX-" usage="cmd"/> + <reg32 offset="0xa9c9" type="a6xx_sp_reg_prog_id_1" name="SP_REG_PROG_ID_1" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xa9ca" type="a6xx_sp_reg_prog_id_2" name="SP_REG_PROG_ID_2" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xa9cb" type="a6xx_sp_reg_prog_id_3" name="SP_REG_PROG_ID_3" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xa9cd" name="SP_CS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A7XX-" usage="cmd"/> <!-- TODO: what does KERNELDIM do exactly (blob sets it differently from turnip) --> - <reg32 offset="0xb990" name="HLSQ_CS_NDRANGE_0" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb990" name="SP_CS_NDRANGE_0" variants="A6XX" usage="rp_blit"> <bitfield name="KERNELDIM" low="0" high="1" type="uint"/> <!-- localsize is value minus one: --> <bitfield name="LOCALSIZEX" low="2" high="11" type="uint"/> <bitfield name="LOCALSIZEY" low="12" high="21" type="uint"/> <bitfield name="LOCALSIZEZ" low="22" high="31" type="uint"/> </reg32> - <reg32 offset="0xb991" name="HLSQ_CS_NDRANGE_1" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb991" name="SP_CS_NDRANGE_1" variants="A6XX" usage="rp_blit"> <bitfield name="GLOBALSIZE_X" low="0" high="31" type="uint"/> </reg32> - <reg32 offset="0xb992" name="HLSQ_CS_NDRANGE_2" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb992" name="SP_CS_NDRANGE_2" variants="A6XX" usage="rp_blit"> <bitfield name="GLOBALOFF_X" low="0" high="31" type="uint"/> </reg32> - <reg32 offset="0xb993" name="HLSQ_CS_NDRANGE_3" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb993" name="SP_CS_NDRANGE_3" variants="A6XX" usage="rp_blit"> <bitfield name="GLOBALSIZE_Y" low="0" high="31" type="uint"/> </reg32> - <reg32 offset="0xb994" name="HLSQ_CS_NDRANGE_4" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb994" name="SP_CS_NDRANGE_4" variants="A6XX" usage="rp_blit"> <bitfield name="GLOBALOFF_Y" low="0" high="31" type="uint"/> </reg32> - <reg32 offset="0xb995" name="HLSQ_CS_NDRANGE_5" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb995" name="SP_CS_NDRANGE_5" variants="A6XX" usage="rp_blit"> <bitfield name="GLOBALSIZE_Z" low="0" high="31" type="uint"/> </reg32> - <reg32 offset="0xb996" name="HLSQ_CS_NDRANGE_6" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb996" name="SP_CS_NDRANGE_6" variants="A6XX" usage="rp_blit"> <bitfield name="GLOBALOFF_Z" low="0" high="31" type="uint"/> </reg32> - <reg32 offset="0xb997" name="HLSQ_CS_CNTL_0" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb997" name="SP_CS_CONST_CONFIG_0" variants="A6XX" usage="rp_blit"> <!-- these are all vec3. first 3 need to be high regs - WGSIZECONSTID is the local size (from HLSQ_CS_NDRANGE_0) + WGSIZECONSTID is the local size (from SP_CS_NDRANGE_0) WGOFFSETCONSTID is WGIDCONSTID*WGSIZECONSTID --> <bitfield name="WGIDCONSTID" low="0" high="7" type="a3xx_regid"/> @@ -5557,7 +4636,7 @@ to upconvert to 32b float internally? <bitfield name="WGOFFSETCONSTID" low="16" high="23" type="a3xx_regid"/> <bitfield name="LOCALIDREGID" low="24" high="31" type="a3xx_regid"/> </reg32> - <reg32 offset="0xb998" name="HLSQ_CS_CNTL_1" variants="A6XX" usage="rp_blit"> + <reg32 offset="0xb998" name="SP_CS_WGE_CNTL" variants="A6XX" usage="rp_blit"> <!-- gl_LocalInvocationIndex --> <bitfield name="LINEARLOCALIDREGID" low="0" high="7" type="a3xx_regid"/> <!-- a650 has 6 "SP cores" (but 3 "SP"). this makes it use only @@ -5569,40 +4648,40 @@ to upconvert to 32b float internally? <bitfield name="THREADSIZE_SCALAR" pos="10" type="boolean"/> </reg32> <!--note: vulkan blob doesn't use these --> - <reg32 offset="0xb999" name="HLSQ_CS_KERNEL_GROUP_X" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xb99a" name="HLSQ_CS_KERNEL_GROUP_Y" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xb99b" name="HLSQ_CS_KERNEL_GROUP_Z" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb999" name="SP_CS_KERNEL_GROUP_X" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb99a" name="SP_CS_KERNEL_GROUP_Y" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xb99b" name="SP_CS_KERNEL_GROUP_Z" variants="A6XX" usage="rp_blit"/> <!-- TODO: what does KERNELDIM do exactly (blob sets it differently from turnip) --> - <reg32 offset="0xa9d4" name="HLSQ_CS_NDRANGE_0" variants="A7XX-" usage="rp_blit"> + <reg32 offset="0xa9d4" name="SP_CS_NDRANGE_0" variants="A7XX-" usage="rp_blit"> <bitfield name="KERNELDIM" low="0" high="1" type="uint"/> <!-- localsize is value minus one: --> <bitfield name="LOCALSIZEX" low="2" high="11" type="uint"/> <bitfield name="LOCALSIZEY" low="12" high="21" type="uint"/> <bitfield name="LOCALSIZEZ" low="22" high="31" type="uint"/> </reg32> - <reg32 offset="0xa9d5" name="HLSQ_CS_NDRANGE_1" variants="A7XX-" usage="rp_blit"> + <reg32 offset="0xa9d5" name="SP_CS_NDRANGE_1" variants="A7XX-" usage="rp_blit"> <bitfield name="GLOBALSIZE_X" low="0" high="31" type="uint"/> </reg32> - <reg32 offset="0xa9d6" name="HLSQ_CS_NDRANGE_2" variants="A7XX-" usage="rp_blit"> + <reg32 offset="0xa9d6" name="SP_CS_NDRANGE_2" variants="A7XX-" usage="rp_blit"> <bitfield name="GLOBALOFF_X" low="0" high="31" type="uint"/> </reg32> - <reg32 offset="0xa9d7" name="HLSQ_CS_NDRANGE_3" variants="A7XX-" usage="rp_blit"> + <reg32 offset="0xa9d7" name="SP_CS_NDRANGE_3" variants="A7XX-" usage="rp_blit"> <bitfield name="GLOBALSIZE_Y" low="0" high="31" type="uint"/> </reg32> - <reg32 offset="0xa9d8" name="HLSQ_CS_NDRANGE_4" variants="A7XX-" usage="rp_blit"> + <reg32 offset="0xa9d8" name="SP_CS_NDRANGE_4" variants="A7XX-" usage="rp_blit"> <bitfield name="GLOBALOFF_Y" low="0" high="31" type="uint"/> </reg32> - <reg32 offset="0xa9d9" name="HLSQ_CS_NDRANGE_5" variants="A7XX-" usage="rp_blit"> + <reg32 offset="0xa9d9" name="SP_CS_NDRANGE_5" variants="A7XX-" usage="rp_blit"> <bitfield name="GLOBALSIZE_Z" low="0" high="31" type="uint"/> </reg32> - <reg32 offset="0xa9da" name="HLSQ_CS_NDRANGE_6" variants="A7XX-" usage="rp_blit"> + <reg32 offset="0xa9da" name="SP_CS_NDRANGE_6" variants="A7XX-" usage="rp_blit"> <bitfield name="GLOBALOFF_Z" low="0" high="31" type="uint"/> </reg32> <!--note: vulkan blob doesn't use these --> - <reg32 offset="0xa9dc" name="HLSQ_CS_KERNEL_GROUP_X" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xa9dd" name="HLSQ_CS_KERNEL_GROUP_Y" variants="A7XX-" usage="rp_blit"/> - <reg32 offset="0xa9de" name="HLSQ_CS_KERNEL_GROUP_Z" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xa9dc" name="SP_CS_KERNEL_GROUP_X" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xa9dd" name="SP_CS_KERNEL_GROUP_Y" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xa9de" name="SP_CS_KERNEL_GROUP_Z" variants="A7XX-" usage="rp_blit"/> <enum name="a7xx_cs_yalign"> <value name="CS_YALIGN_1" value="8"/> @@ -5611,19 +4690,29 @@ to upconvert to 32b float internally? <value name="CS_YALIGN_8" value="1"/> </enum> - <reg32 offset="0xa9db" name="HLSQ_CS_CNTL_1" variants="A7XX-" usage="rp_blit"> + <reg32 offset="0xa9db" name="SP_CS_WGE_CNTL" variants="A7XX-" usage="rp_blit"> <!-- gl_LocalInvocationIndex --> <bitfield name="LINEARLOCALIDREGID" low="0" high="7" type="a3xx_regid"/> <!-- Must match SP_CS_CTRL --> <bitfield name="THREADSIZE" pos="9" type="a6xx_threadsize"/> - <bitfield name="UNK11" pos="11" type="boolean"/> - <bitfield name="UNK22" pos="22" type="boolean"/> - <bitfield name="UNK26" pos="26" type="boolean"/> - <bitfield name="YALIGN" low="27" high="30" type="a7xx_cs_yalign"/> + <doc> + When this bit is enabled, the dispatch order interleaves + the z coordinate instead of launching all workgroups + with z=0, then all with z=1 and so on. + </doc> + <bitfield name="WORKGROUPRASTORDERZFIRSTEN" pos="11" type="boolean"/> + <doc> + When both fields are non-0 then the dispatcher uses + these tile sizes to launch workgroups in a tiled manner + when the x and y workgroup counts are + both more than 1. + </doc> + <bitfield name="WGTILEWIDTH" low="20" high="25"/> + <bitfield name="WGTILEHEIGHT" low="26" high="31"/> </reg32> - <reg32 offset="0xa9df" name="HLSQ_CS_LOCAL_SIZE" variants="A7XX-" usage="cmd"> - <!-- localsize is value minus one: --> + <reg32 offset="0xa9df" name="SP_CS_NDRANGE_7" variants="A7XX-" usage="cmd"> + <!-- The size of the last workgroup. localsize is value minus one: --> <bitfield name="LOCALSIZEX" low="2" high="11" type="uint"/> <bitfield name="LOCALSIZEY" low="12" high="21" type="uint"/> <bitfield name="LOCALSIZEZ" low="22" high="31" type="uint"/> @@ -5641,29 +4730,27 @@ to upconvert to 32b float internally? </reg64> </array> - <!-- new in a6xx gen4, mirror of SP_CS_UNKNOWN_A9B1? --> - <reg32 offset="0xb9d0" name="HLSQ_CS_UNKNOWN_B9D0" variants="A6XX" usage="cmd"> + <!-- new in a6xx gen4, mirror of SP_CS_CNTL_1? --> + <reg32 offset="0xb9d0" name="HLSQ_CS_CTRL_REG1" variants="A6XX" usage="cmd"> <bitfield name="SHARED_SIZE" low="0" high="4" type="uint"/> - <bitfield name="UNK5" pos="5" type="boolean"/> - <!-- always 1 ? --> - <bitfield name="UNK6" pos="6" type="boolean"/> + <bitfield name="CONSTANTRAMMODE" low="5" high="6" type="a6xx_const_ram_mode"/> </reg32> - <reg32 offset="0xbb00" name="HLSQ_DRAW_CMD" variants="A6XX"> + <reg32 offset="0xbb00" name="SP_DRAW_INITIATOR" variants="A6XX"> <bitfield name="STATE_ID" low="0" high="7"/> </reg32> - <reg32 offset="0xbb01" name="HLSQ_DISPATCH_CMD" variants="A6XX"> + <reg32 offset="0xbb01" name="SP_KERNEL_INITIATOR" variants="A6XX"> <bitfield name="STATE_ID" low="0" high="7"/> </reg32> - <reg32 offset="0xbb02" name="HLSQ_EVENT_CMD" variants="A6XX"> + <reg32 offset="0xbb02" name="SP_EVENT_INITIATOR" variants="A6XX"> <!-- I think only the low bit is actually used? --> <bitfield name="STATE_ID" low="16" high="23"/> <bitfield name="EVENT" low="0" high="6" type="vgt_event_type"/> </reg32> - <reg32 offset="0xbb08" name="HLSQ_INVALIDATE_CMD" variants="A6XX" usage="cmd"> + <reg32 offset="0xbb08" name="SP_UPDATE_CNTL" variants="A6XX" usage="cmd"> <doc> This register clears pending loads queued up by CP_LOAD_STATE6. Each bit resets a particular kind(s) of @@ -5678,8 +4765,8 @@ to upconvert to 32b float internally? <bitfield name="FS_STATE" pos="4" type="boolean"/> <bitfield name="CS_STATE" pos="5" type="boolean"/> - <bitfield name="CS_IBO" pos="6" type="boolean"/> - <bitfield name="GFX_IBO" pos="7" type="boolean"/> + <bitfield name="CS_UAV" pos="6" type="boolean"/> + <bitfield name="GFX_UAV" pos="7" type="boolean"/> <!-- Note: these only do something when HLSQ_SHARED_CONSTS is set to 1 --> <bitfield name="CS_SHARED_CONST" pos="19" type="boolean"/> @@ -5690,20 +4777,20 @@ to upconvert to 32b float internally? <bitfield name="GFX_BINDLESS" low="14" high="18" type="hex"/> </reg32> - <reg32 offset="0xab1c" name="HLSQ_DRAW_CMD" variants="A7XX-"> + <reg32 offset="0xab1c" name="SP_DRAW_INITIATOR" variants="A7XX-"> <bitfield name="STATE_ID" low="0" high="7"/> </reg32> - <reg32 offset="0xab1d" name="HLSQ_DISPATCH_CMD" variants="A7XX-"> + <reg32 offset="0xab1d" name="SP_KERNEL_INITIATOR" variants="A7XX-"> <bitfield name="STATE_ID" low="0" high="7"/> </reg32> - <reg32 offset="0xab1e" name="HLSQ_EVENT_CMD" variants="A7XX-"> + <reg32 offset="0xab1e" name="SP_EVENT_INITIATOR" variants="A7XX-"> <bitfield name="STATE_ID" low="16" high="23"/> <bitfield name="EVENT" low="0" high="6" type="vgt_event_type"/> </reg32> - <reg32 offset="0xab1f" name="HLSQ_INVALIDATE_CMD" variants="A7XX-" usage="cmd"> + <reg32 offset="0xab1f" name="SP_UPDATE_CNTL" variants="A7XX" usage="cmd"> <doc> This register clears pending loads queued up by CP_LOAD_STATE6. Each bit resets a particular kind(s) of @@ -5718,18 +4805,38 @@ to upconvert to 32b float internally? <bitfield name="FS_STATE" pos="4" type="boolean"/> <bitfield name="CS_STATE" pos="5" type="boolean"/> - <bitfield name="CS_IBO" pos="6" type="boolean"/> - <bitfield name="GFX_IBO" pos="7" type="boolean"/> + <bitfield name="CS_UAV" pos="6" type="boolean"/> + <bitfield name="GFX_UAV" pos="7" type="boolean"/> <!-- SS6_BINDLESS: one bit per bindless base --> <bitfield name="CS_BINDLESS" low="9" high="16" type="hex"/> <bitfield name="GFX_BINDLESS" low="17" high="24" type="hex"/> </reg32> - <reg32 offset="0xbb10" name="HLSQ_FS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A6XX" usage="rp_blit"/> - <reg32 offset="0xab03" name="HLSQ_FS_CNTL" type="a6xx_hlsq_xs_cntl" variants="A7XX-" usage="rp_blit"/> + <reg32 offset="0xab1f" name="SP_UPDATE_CNTL" variants="A8XX" usage="cmd"> + <doc> + This register clears pending loads queued up by + CP_LOAD_STATE6. Each bit resets a particular kind(s) of + CP_LOAD_STATE6. + </doc> + + <!-- per-stage state: shader, non-bindless UBO, textures, and samplers --> + <bitfield name="VS_STATE" pos="0" type="boolean"/> + <bitfield name="HS_STATE" pos="1" type="boolean"/> + <bitfield name="DS_STATE" pos="2" type="boolean"/> + <bitfield name="GS_STATE" pos="3" type="boolean"/> + <bitfield name="FS_STATE" pos="4" type="boolean"/> + <bitfield name="CS_STATE" pos="5" type="boolean"/> + </reg32> + + <reg32 offset="0xa9c0" name="SP_CS_BINDLESS_INVALIDATE"/> + <reg32 offset="0xab08" name="SP_GFX_BINDLESS_INVALIDATE"/> - <array offset="0xab40" name="HLSQ_SHARED_CONSTS_IMM" stride="1" length="64" variants="A7XX-"/> + <reg32 offset="0xbb10" name="SP_PS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A6XX" usage="rp_blit"/> + <reg32 offset="0xab03" name="SP_PS_CONST_CONFIG" type="a6xx_xs_const_config" variants="A7XX-" usage="rp_blit"/> + + <array offset="0xab40" name="SP_SHARED_CONSTANT_GFX" stride="1" length="64" variants="A7XX"/> + <array offset="0xab30" name="SP_SHARED_CONSTANT_GFX" stride="1" length="128" variants="A8XX-"/> <reg32 offset="0xbb11" name="HLSQ_SHARED_CONSTS" variants="A6XX" usage="cmd"> <doc> @@ -5738,7 +4845,7 @@ to upconvert to 32b float internally? const pool and 16 in the geometry const pool although only 8 are actually used (why?) and they are mapped to c504-c511 in each stage. Both VS and FS shared consts - are written using ST6_CONSTANTS/SB6_IBO, so that both + are written using ST6_CONSTANTS/SB6_UAV, so that both the geometry and FS shared consts can be written at once by using CP_LOAD_STATE6 rather than CP_LOAD_STATE6_FRAG/CP_LOAD_STATE6_GEOM. In addition @@ -5747,13 +4854,13 @@ to upconvert to 32b float internally? There is also a separate shared constant pool for CS, which is loaded through CP_LOAD_STATE6_FRAG with - ST6_UBO/ST6_IBO. However the only real difference for CS + ST6_UBO/ST6_UAV. However the only real difference for CS is the dword units. </doc> <bitfield name="ENABLE" pos="0" type="boolean"/> </reg32> - <!-- mirror of SP_BINDLESS_BASE --> + <!-- mirror of SP_GFX_BINDLESS_BASE --> <array offset="0xbb20" name="HLSQ_BINDLESS_BASE" stride="2" length="5" variants="A6XX" usage="cmd"> <reg64 offset="0" name="DESCRIPTOR"> <bitfield name="DESC_SIZE" low="0" high="1" type="a6xx_bindless_descriptor_size"/> @@ -5766,15 +4873,15 @@ to upconvert to 32b float internally? <bitfield name="EVENT" low="0" high="6" type="vgt_event_type"/> </reg32> - <reg32 offset="0xbe00" name="HLSQ_UNKNOWN_BE00" variants="A6XX" usage="cmd"/> <!-- all bits valid except bit 29 --> - <reg32 offset="0xbe01" name="HLSQ_UNKNOWN_BE01" low="4" high="6" variants="A6XX" usage="cmd"/> - <reg32 offset="0xbe04" name="HLSQ_DBG_ECO_CNTL" variants="A6XX" usage="cmd"/> - <reg32 offset="0xbe05" name="HLSQ_ADDR_MODE_CNTL" type="a5xx_address_mode"/> + <reg32 offset="0xbe00" name="HLSQ_UNKNOWN_BE00" variants="A6XX" usage="init"/> <!-- all bits valid except bit 29 --> + <reg32 offset="0xbe01" name="HLSQ_UNKNOWN_BE01" low="4" high="6" variants="A6XX" usage="init"/> + <reg32 offset="0xbe04" name="HLSQ_DBG_ECO_CNTL" variants="A6XX" usage="init"/> + <reg32 offset="0xbe05" name="HLSQ_ADDR_MODE_CNTL" type="a5xx_address_mode" variants="A6XX"/> <reg32 offset="0xbe08" name="HLSQ_UNKNOWN_BE08" low="0" high="15"/> <array offset="0xbe10" name="HLSQ_PERFCTR_HLSQ_SEL" stride="1" length="6"/> <!-- TODO: some valid registers between 0xbe20 and 0xbe33 --> - <reg32 offset="0xbe22" name="HLSQ_CONTEXT_SWITCH_GFX_PREEMPTION_SAFE_MODE"/> + <reg32 offset="0xbe22" name="HLSQ_CONTEXT_SWITCH_GFX_PREEMPTION_SAFE_MODE" variants="A6XX"/> <reg32 offset="0xc000" name="SP_AHB_READ_APERTURE" variants="A7XX-"/> @@ -5788,10 +4895,10 @@ to upconvert to 32b float internally? sequence. The sequence used internally for an event looks like: - write EVENT_CMD pipe register - write CP_EVENT_START - - write HLSQ_EVENT_CMD with event or HLSQ_DRAW_CMD - - write PC_EVENT_CMD with event or PC_DRAW_CMD - - write HLSQ_EVENT_CMD(CONTEXT_DONE) - - write PC_EVENT_CMD(CONTEXT_DONE) + - write SP_EVENT_INITIATOR with event or SP_DRAW_INITIATOR + - write PC_EVENT_INITIATOR with event or PC_DRAW_INITIATOR + - write SP_EVENT_INITIATOR(CONTEXT_DONE) + - write PC_EVENT_INITIATOR(CONTEXT_DONE) - write CP_EVENT_END Writing to CP_EVENT_END seems to actually trigger the context roll --> @@ -5809,193 +4916,6 @@ to upconvert to 32b float internally? </reg32> </domain> -<!-- Seems basically the same as a5xx, maybe move to common.xml.. --> -<domain name="A6XX_TEX_SAMP" width="32"> - <doc>Texture sampler dwords</doc> - <enum name="a6xx_tex_filter"> <!-- same as a4xx? --> - <value name="A6XX_TEX_NEAREST" value="0"/> - <value name="A6XX_TEX_LINEAR" value="1"/> - <value name="A6XX_TEX_ANISO" value="2"/> - <value name="A6XX_TEX_CUBIC" value="3"/> <!-- a650 only --> - </enum> - <enum name="a6xx_tex_clamp"> <!-- same as a4xx? --> - <value name="A6XX_TEX_REPEAT" value="0"/> - <value name="A6XX_TEX_CLAMP_TO_EDGE" value="1"/> - <value name="A6XX_TEX_MIRROR_REPEAT" value="2"/> - <value name="A6XX_TEX_CLAMP_TO_BORDER" value="3"/> - <value name="A6XX_TEX_MIRROR_CLAMP" value="4"/> - </enum> - <enum name="a6xx_tex_aniso"> <!-- same as a4xx? --> - <value name="A6XX_TEX_ANISO_1" value="0"/> - <value name="A6XX_TEX_ANISO_2" value="1"/> - <value name="A6XX_TEX_ANISO_4" value="2"/> - <value name="A6XX_TEX_ANISO_8" value="3"/> - <value name="A6XX_TEX_ANISO_16" value="4"/> - </enum> - <enum name="a6xx_reduction_mode"> - <value name="A6XX_REDUCTION_MODE_AVERAGE" value="0"/> - <value name="A6XX_REDUCTION_MODE_MIN" value="1"/> - <value name="A6XX_REDUCTION_MODE_MAX" value="2"/> - </enum> - - <reg32 offset="0" name="0"> - <bitfield name="MIPFILTER_LINEAR_NEAR" pos="0" type="boolean"/> - <bitfield name="XY_MAG" low="1" high="2" type="a6xx_tex_filter"/> - <bitfield name="XY_MIN" low="3" high="4" type="a6xx_tex_filter"/> - <bitfield name="WRAP_S" low="5" high="7" type="a6xx_tex_clamp"/> - <bitfield name="WRAP_T" low="8" high="10" type="a6xx_tex_clamp"/> - <bitfield name="WRAP_R" low="11" high="13" type="a6xx_tex_clamp"/> - <bitfield name="ANISO" low="14" high="16" type="a6xx_tex_aniso"/> - <bitfield name="LOD_BIAS" low="19" high="31" type="fixed" radix="8"/><!-- no idea how many bits for real --> - </reg32> - <reg32 offset="1" name="1"> - <bitfield name="CLAMPENABLE" pos="0" type="boolean"> - <doc> - clamp result to [0, 1] if the format is unorm or - [-1, 1] if the format is snorm, *after* - filtering. Has no effect for other formats. - </doc> - </bitfield> - <bitfield name="COMPARE_FUNC" low="1" high="3" type="adreno_compare_func"/> - <bitfield name="CUBEMAPSEAMLESSFILTOFF" pos="4" type="boolean"/> - <bitfield name="UNNORM_COORDS" pos="5" type="boolean"/> - <bitfield name="MIPFILTER_LINEAR_FAR" pos="6" type="boolean"/> - <bitfield name="MAX_LOD" low="8" high="19" type="ufixed" radix="8"/> - <bitfield name="MIN_LOD" low="20" high="31" type="ufixed" radix="8"/> - </reg32> - <reg32 offset="2" name="2"> - <bitfield name="REDUCTION_MODE" low="0" high="1" type="a6xx_reduction_mode"/> - <bitfield name="CHROMA_LINEAR" pos="5" type="boolean"/> - <bitfield name="BCOLOR" low="7" high="31"/> - </reg32> - <reg32 offset="3" name="3"/> -</domain> - -<domain name="A6XX_TEX_CONST" width="32" varset="chip"> - <doc>Texture constant dwords</doc> - <enum name="a6xx_tex_swiz"> <!-- same as a4xx? --> - <value name="A6XX_TEX_X" value="0"/> - <value name="A6XX_TEX_Y" value="1"/> - <value name="A6XX_TEX_Z" value="2"/> - <value name="A6XX_TEX_W" value="3"/> - <value name="A6XX_TEX_ZERO" value="4"/> - <value name="A6XX_TEX_ONE" value="5"/> - </enum> - <enum name="a6xx_tex_type"> <!-- same as a4xx? --> - <value name="A6XX_TEX_1D" value="0"/> - <value name="A6XX_TEX_2D" value="1"/> - <value name="A6XX_TEX_CUBE" value="2"/> - <value name="A6XX_TEX_3D" value="3"/> - <value name="A6XX_TEX_BUFFER" value="4"/> - </enum> - <reg32 offset="0" name="0"> - <bitfield name="TILE_MODE" low="0" high="1" type="a6xx_tile_mode"/> - <bitfield name="SRGB" pos="2" type="boolean"/> - <bitfield name="SWIZ_X" low="4" high="6" type="a6xx_tex_swiz"/> - <bitfield name="SWIZ_Y" low="7" high="9" type="a6xx_tex_swiz"/> - <bitfield name="SWIZ_Z" low="10" high="12" type="a6xx_tex_swiz"/> - <bitfield name="SWIZ_W" low="13" high="15" type="a6xx_tex_swiz"/> - <bitfield name="MIPLVLS" low="16" high="19" type="uint"/> - <!-- overlaps with MIPLVLS --> - <bitfield name="CHROMA_MIDPOINT_X" pos="16" type="boolean"/> - <bitfield name="CHROMA_MIDPOINT_Y" pos="18" type="boolean"/> - <bitfield name="SAMPLES" low="20" high="21" type="a3xx_msaa_samples"/> - <bitfield name="FMT" low="22" high="29" type="a6xx_format"/> - <!-- - Why is the swap needed in addition to SWIZ_*? The swap - is performed before border color replacement, while the - swizzle is applied after after it. - --> - <bitfield name="SWAP" low="30" high="31" type="a3xx_color_swap"/> - </reg32> - <reg32 offset="1" name="1"> - <bitfield name="WIDTH" low="0" high="14" type="uint"/> - <bitfield name="HEIGHT" low="15" high="29" type="uint"/> - <bitfield name="MUTABLEEN" pos="31" type="boolean" variants="A7XX-"/> - </reg32> - <reg32 offset="2" name="2"> - <!-- - These fields overlap PITCH, and are used instead of - PITCH/PITCHALIGN when TYPE is A6XX_TEX_BUFFER. - --> - <doc> probably for D3D structured UAVs, normally set to 1 </doc> - <bitfield name="STRUCTSIZETEXELS" low="4" high="15" type="uint"/> - <bitfield name="STARTOFFSETTEXELS" low="16" high="21" type="uint"/> - - <!-- minimum pitch (for mipmap levels): log2(pitchalign / 64) --> - <bitfield name="PITCHALIGN" low="0" high="3" type="uint"/> - <doc>Pitch in bytes (so actually stride)</doc> - <bitfield name="PITCH" low="7" high="28" type="uint"/> - <bitfield name="TYPE" low="29" high="31" type="a6xx_tex_type"/> - </reg32> - <reg32 offset="3" name="3"> - <!-- - ARRAY_PITCH is basically LAYERSZ for the first mipmap level, and - for 3d textures (laid out mipmap level first) MIN_LAYERSZ is the - layer size at the point that it stops being reduced moving to - higher (smaller) mipmap levels - --> - <bitfield name="ARRAY_PITCH" low="0" high="22" shr="12" type="uint"/> - <bitfield name="MIN_LAYERSZ" low="23" high="26" shr="12"/> - <!-- - by default levels with w < 16 are linear - TILE_ALL makes all levels have tiling - seems required when using UBWC, since all levels have UBWC (can possibly be disabled?) - --> - <bitfield name="TILE_ALL" pos="27" type="boolean"/> - <bitfield name="FLAG" pos="28" type="boolean"/> - </reg32> - <!-- for 2-3 plane format, BASE is flag buffer address (if enabled) - the address of the non-flag base buffer is determined automatically, - and must follow the flag buffer - --> - <reg32 offset="4" name="4"> - <bitfield name="BASE_LO" low="5" high="31" shr="5"/> - </reg32> - <reg32 offset="5" name="5"> - <bitfield name="BASE_HI" low="0" high="16"/> - <bitfield name="DEPTH" low="17" high="29" type="uint"/> - </reg32> - <reg32 offset="6" name="6"> - <!-- overlaps with PLANE_PITCH --> - <bitfield name="MIN_LOD_CLAMP" low="0" high="11" type="ufixed" radix="8"/> - <!-- pitch for plane 2 / plane 3 --> - <bitfield name="PLANE_PITCH" low="8" high="31" type="uint"/> - </reg32> - <!-- 7/8 is plane 2 address for planar formats --> - <reg32 offset="7" name="7"> - <bitfield name="FLAG_LO" low="5" high="31" shr="5"/> - </reg32> - <reg32 offset="8" name="8"> - <bitfield name="FLAG_HI" low="0" high="16"/> - </reg32> - <!-- 9/10 is plane 3 address for planar formats --> - <reg32 offset="9" name="9"> - <bitfield name="FLAG_BUFFER_ARRAY_PITCH" low="0" high="16" shr="4" type="uint"/> - </reg32> - <reg32 offset="10" name="10"> - <bitfield name="FLAG_BUFFER_PITCH" low="0" high="6" shr="6" type="uint"/> - <!-- log2 size of the first level, required for mipmapping --> - <bitfield name="FLAG_BUFFER_LOGW" low="8" high="11" type="uint"/> - <bitfield name="FLAG_BUFFER_LOGH" low="12" high="15" type="uint"/> - </reg32> - <reg32 offset="11" name="11"/> - <reg32 offset="12" name="12"/> - <reg32 offset="13" name="13"/> - <reg32 offset="14" name="14"/> - <reg32 offset="15" name="15"/> -</domain> - -<domain name="A6XX_UBO" width="32"> - <reg32 offset="0" name="0"> - <bitfield name="BASE_LO" low="0" high="31"/> - </reg32> - <reg32 offset="1" name="1"> - <bitfield name="BASE_HI" low="0" high="16"/> - <bitfield name="SIZE" low="17" high="31"/> <!-- size in vec4 (4xDWORD) units --> - </reg32> -</domain> - <domain name="A6XX_PDC" width="32"> <reg32 offset="0x1140" name="GPU_ENABLE_PDC"/> <reg32 offset="0x1148" name="GPU_SEQ_START_ADDR"/> @@ -6078,10 +4998,19 @@ to upconvert to 32b float internally? <reg32 offset="0x0030" name="CFG_DBGBUS_TRACE_BUF2"/> </domain> +<domain name="A7XX_CX_DBGC" width="32" varset="chip"> + <!-- Bitfields shifted, but otherwise the same: --> + <reg32 offset="0x0000" name="CFG_DBGBUS_SEL_A" variants="A7XX-"> + <bitfield high="7" low="0" name="PING_INDEX"/> + <bitfield high="24" low="16" name="PING_BLK_SEL"/> + </reg32> +</domain> + <domain name="A6XX_CX_MISC" width="32" prefix="variant" varset="chip"> <reg32 offset="0x0001" name="SYSTEM_CACHE_CNTL_0"/> <reg32 offset="0x0002" name="SYSTEM_CACHE_CNTL_1"/> <reg32 offset="0x0039" name="CX_MISC_TCM_RET_CNTL" variants="A7XX-"/> + <reg32 offset="0x0087" name="CX_MISC_SLICE_ENABLE_FINAL" variants="A8XX"/> <reg32 offset="0x0400" name="CX_MISC_SW_FUSE_VALUE" variants="A7XX-"> <bitfield pos="0" name="FASTBLEND" type="boolean"/> <bitfield pos="1" name="LPAC" type="boolean"/> diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx_descriptors.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx_descriptors.xml new file mode 100644 index 000000000000..56cfaff614a4 --- /dev/null +++ b/drivers/gpu/drm/msm/registers/adreno/a6xx_descriptors.xml @@ -0,0 +1,158 @@ +<?xml version="1.0" encoding="UTF-8"?> +<database xmlns="http://nouveau.freedesktop.org/" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> +<import file="freedreno_copyright.xml"/> +<import file="adreno/adreno_common.xml"/> +<import file="adreno/adreno_pm4.xml"/> +<import file="adreno/a6xx_enums.xml"/> + +<domain name="A6XX_TEX_SAMP" width="32"> + <doc>Texture sampler dwords</doc> + + <reg32 offset="0" name="0"> + <bitfield name="MIPFILTER_LINEAR_NEAR" pos="0" type="boolean"/> + <bitfield name="XY_MAG" low="1" high="2" type="a6xx_tex_filter"/> + <bitfield name="XY_MIN" low="3" high="4" type="a6xx_tex_filter"/> + <bitfield name="WRAP_S" low="5" high="7" type="a6xx_tex_clamp"/> + <bitfield name="WRAP_T" low="8" high="10" type="a6xx_tex_clamp"/> + <bitfield name="WRAP_R" low="11" high="13" type="a6xx_tex_clamp"/> + <bitfield name="ANISO" low="14" high="16" type="a6xx_tex_aniso"/> + <bitfield name="LOD_BIAS" low="19" high="31" type="fixed" radix="8"/><!-- no idea how many bits for real --> + </reg32> + <reg32 offset="1" name="1"> + <bitfield name="CLAMPENABLE" pos="0" type="boolean"> + <doc> + clamp result to [0, 1] if the format is unorm or + [-1, 1] if the format is snorm, *after* + filtering. Has no effect for other formats. + </doc> + </bitfield> + <bitfield name="COMPARE_FUNC" low="1" high="3" type="adreno_compare_func"/> + <bitfield name="CUBEMAPSEAMLESSFILTOFF" pos="4" type="boolean"/> + <bitfield name="UNNORM_COORDS" pos="5" type="boolean"/> + <bitfield name="MIPFILTER_LINEAR_FAR" pos="6" type="boolean"/> + <bitfield name="MAX_LOD" low="8" high="19" type="ufixed" radix="8"/> + <bitfield name="MIN_LOD" low="20" high="31" type="ufixed" radix="8"/> + </reg32> + <reg32 offset="2" name="2"> + <bitfield name="REDUCTION_MODE" low="0" high="1" type="a6xx_reduction_mode"/> + <bitfield name="FASTBORDERCOLOR" low="2" high="3" type="a6xx_fast_border_color"/> + <bitfield name="FASTBORDERCOLOREN" pos="4" type="boolean"/> + <bitfield name="CHROMA_LINEAR" pos="5" type="boolean"/> + <bitfield name="BCOLOR" low="7" high="31"/> + </reg32> + <reg32 offset="3" name="3"/> +</domain> + +<domain name="A6XX_TEX_CONST" width="32" varset="chip"> + <doc>Texture constant dwords</doc> + <reg32 offset="0" name="0"> + <bitfield name="TILE_MODE" low="0" high="1" type="a6xx_tile_mode"/> + <bitfield name="SRGB" pos="2" type="boolean"/> + <bitfield name="SWIZ_X" low="4" high="6" type="a6xx_tex_swiz"/> + <bitfield name="SWIZ_Y" low="7" high="9" type="a6xx_tex_swiz"/> + <bitfield name="SWIZ_Z" low="10" high="12" type="a6xx_tex_swiz"/> + <bitfield name="SWIZ_W" low="13" high="15" type="a6xx_tex_swiz"/> + <bitfield name="MIPLVLS" low="16" high="19" type="uint"/> + <!-- overlaps with MIPLVLS --> + <bitfield name="CHROMA_MIDPOINT_X" pos="16" type="boolean"/> + <bitfield name="CHROMA_MIDPOINT_Y" pos="18" type="boolean"/> + <bitfield name="SAMPLES" low="20" high="21" type="a3xx_msaa_samples"/> + <bitfield name="FMT" low="22" high="29" type="a6xx_format"/> + <!-- + Why is the swap needed in addition to SWIZ_*? The swap + is performed before border color replacement, while the + swizzle is applied after after it. + --> + <bitfield name="SWAP" low="30" high="31" type="a3xx_color_swap"/> + </reg32> + <reg32 offset="1" name="1"> + <bitfield name="WIDTH" low="0" high="14" type="uint"/> + <bitfield name="HEIGHT" low="15" high="29" type="uint"/> + <bitfield name="MUTABLEEN" pos="31" type="boolean" variants="A7XX-"/> + </reg32> + <reg32 offset="2" name="2"> + <!-- + These fields overlap PITCH, and are used instead of + PITCH/PITCHALIGN when TYPE is A6XX_TEX_BUFFER. + --> + <doc> probably for D3D structured UAVs, normally set to 1 </doc> + <bitfield name="STRUCTSIZETEXELS" low="4" high="15" type="uint"/> + <bitfield name="STARTOFFSETTEXELS" low="16" high="21" type="uint"/> + + <!-- minimum pitch (for mipmap levels): log2(pitchalign / 64) --> + <bitfield name="PITCHALIGN" low="0" high="3" type="uint"/> + <doc>Pitch in bytes (so actually stride)</doc> + <bitfield name="PITCH" low="7" high="28" type="uint"/> + <bitfield name="TYPE" low="29" high="31" type="a6xx_tex_type"/> + </reg32> + <reg32 offset="3" name="3"> + <!-- + ARRAY_PITCH is basically LAYERSZ for the first mipmap level, and + for 3d textures (laid out mipmap level first) MIN_LAYERSZ is the + layer size at the point that it stops being reduced moving to + higher (smaller) mipmap levels + --> + <bitfield name="ARRAY_PITCH" low="0" high="22" shr="12" type="uint"/> + <bitfield name="MIN_LAYERSZ" low="23" high="26" shr="12"/> + <!-- + by default levels with w < 16 are linear + TILE_ALL makes all levels have tiling + seems required when using UBWC, since all levels have UBWC (can possibly be disabled?) + --> + <bitfield name="TILE_ALL" pos="27" type="boolean"/> + <bitfield name="FLAG" pos="28" type="boolean"/> + </reg32> + <!-- for 2-3 plane format, BASE is flag buffer address (if enabled) + the address of the non-flag base buffer is determined automatically, + and must follow the flag buffer + --> + <reg32 offset="4" name="4"> + <bitfield name="BASE_LO" low="5" high="31" shr="5"/> + </reg32> + <reg32 offset="5" name="5"> + <bitfield name="BASE_HI" low="0" high="16"/> + <bitfield name="DEPTH" low="17" high="29" type="uint"/> + </reg32> + <reg32 offset="6" name="6"> + <!-- overlaps with PLANE_PITCH --> + <bitfield name="MIN_LOD_CLAMP" low="0" high="11" type="ufixed" radix="8"/> + <!-- pitch for plane 2 / plane 3 --> + <bitfield name="PLANE_PITCH" low="8" high="31" type="uint"/> + </reg32> + <!-- 7/8 is plane 2 address for planar formats --> + <reg32 offset="7" name="7"> + <bitfield name="FLAG_LO" low="5" high="31" shr="5"/> + </reg32> + <reg32 offset="8" name="8"> + <bitfield name="FLAG_HI" low="0" high="16"/> + </reg32> + <!-- 9/10 is plane 3 address for planar formats --> + <reg32 offset="9" name="9"> + <bitfield name="FLAG_BUFFER_ARRAY_PITCH" low="0" high="16" shr="4" type="uint"/> + </reg32> + <reg32 offset="10" name="10"> + <bitfield name="FLAG_BUFFER_PITCH" low="0" high="6" shr="6" type="uint"/> + <!-- log2 size of the first level, required for mipmapping --> + <bitfield name="FLAG_BUFFER_LOGW" low="8" high="11" type="uint"/> + <bitfield name="FLAG_BUFFER_LOGH" low="12" high="15" type="uint"/> + </reg32> + <reg32 offset="11" name="11"/> + <reg32 offset="12" name="12"/> + <reg32 offset="13" name="13"/> + <reg32 offset="14" name="14"/> + <reg32 offset="15" name="15"/> +</domain> + +<domain name="A6XX_UBO" width="32"> + <reg32 offset="0" name="0"> + <bitfield name="BASE_LO" low="0" high="31"/> + </reg32> + <reg32 offset="1" name="1"> + <bitfield name="BASE_HI" low="0" high="16"/> + <bitfield name="SIZE" low="17" high="31"/> <!-- size in vec4 (4xDWORD) units --> + </reg32> +</domain> + +</database> diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx_enums.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx_enums.xml new file mode 100644 index 000000000000..81538831dc19 --- /dev/null +++ b/drivers/gpu/drm/msm/registers/adreno/a6xx_enums.xml @@ -0,0 +1,429 @@ +<?xml version="1.0" encoding="UTF-8"?> +<database xmlns="http://nouveau.freedesktop.org/" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> +<import file="freedreno_copyright.xml"/> +<import file="adreno/adreno_common.xml"/> +<import file="adreno/adreno_pm4.xml"/> + +<enum name="a6xx_tile_mode"> + <value name="TILE6_LINEAR" value="0"/> + <value name="TILE6_2" value="2"/> + <value name="TILE6_3" value="3"/> +</enum> + +<enum name="a6xx_format"> + <value value="0x02" name="FMT6_A8_UNORM"/> + <value value="0x03" name="FMT6_8_UNORM"/> + <value value="0x04" name="FMT6_8_SNORM"/> + <value value="0x05" name="FMT6_8_UINT"/> + <value value="0x06" name="FMT6_8_SINT"/> + + <value value="0x08" name="FMT6_4_4_4_4_UNORM"/> + <value value="0x0a" name="FMT6_5_5_5_1_UNORM"/> + <value value="0x0c" name="FMT6_1_5_5_5_UNORM"/> <!-- read only --> + <value value="0x0e" name="FMT6_5_6_5_UNORM"/> + + <value value="0x0f" name="FMT6_8_8_UNORM"/> + <value value="0x10" name="FMT6_8_8_SNORM"/> + <value value="0x11" name="FMT6_8_8_UINT"/> + <value value="0x12" name="FMT6_8_8_SINT"/> + <value value="0x13" name="FMT6_L8_A8_UNORM"/> + + <value value="0x15" name="FMT6_16_UNORM"/> + <value value="0x16" name="FMT6_16_SNORM"/> + <value value="0x17" name="FMT6_16_FLOAT"/> + <value value="0x18" name="FMT6_16_UINT"/> + <value value="0x19" name="FMT6_16_SINT"/> + + <value value="0x21" name="FMT6_8_8_8_UNORM"/> + <value value="0x22" name="FMT6_8_8_8_SNORM"/> + <value value="0x23" name="FMT6_8_8_8_UINT"/> + <value value="0x24" name="FMT6_8_8_8_SINT"/> + + <value value="0x30" name="FMT6_8_8_8_8_UNORM"/> + <value value="0x31" name="FMT6_8_8_8_X8_UNORM"/> <!-- samples 1 for alpha --> + <value value="0x32" name="FMT6_8_8_8_8_SNORM"/> + <value value="0x33" name="FMT6_8_8_8_8_UINT"/> + <value value="0x34" name="FMT6_8_8_8_8_SINT"/> + + <value value="0x35" name="FMT6_9_9_9_E5_FLOAT"/> + + <value value="0x36" name="FMT6_10_10_10_2_UNORM"/> + <value value="0x37" name="FMT6_10_10_10_2_UNORM_DEST"/> + <value value="0x39" name="FMT6_10_10_10_2_SNORM"/> + <value value="0x3a" name="FMT6_10_10_10_2_UINT"/> + <value value="0x3b" name="FMT6_10_10_10_2_SINT"/> + + <value value="0x42" name="FMT6_11_11_10_FLOAT"/> + + <value value="0x43" name="FMT6_16_16_UNORM"/> + <value value="0x44" name="FMT6_16_16_SNORM"/> + <value value="0x45" name="FMT6_16_16_FLOAT"/> + <value value="0x46" name="FMT6_16_16_UINT"/> + <value value="0x47" name="FMT6_16_16_SINT"/> + + <value value="0x48" name="FMT6_32_UNORM"/> + <value value="0x49" name="FMT6_32_SNORM"/> + <value value="0x4a" name="FMT6_32_FLOAT"/> + <value value="0x4b" name="FMT6_32_UINT"/> + <value value="0x4c" name="FMT6_32_SINT"/> + <value value="0x4d" name="FMT6_32_FIXED"/> + + <value value="0x58" name="FMT6_16_16_16_UNORM"/> + <value value="0x59" name="FMT6_16_16_16_SNORM"/> + <value value="0x5a" name="FMT6_16_16_16_FLOAT"/> + <value value="0x5b" name="FMT6_16_16_16_UINT"/> + <value value="0x5c" name="FMT6_16_16_16_SINT"/> + + <value value="0x60" name="FMT6_16_16_16_16_UNORM"/> + <value value="0x61" name="FMT6_16_16_16_16_SNORM"/> + <value value="0x62" name="FMT6_16_16_16_16_FLOAT"/> + <value value="0x63" name="FMT6_16_16_16_16_UINT"/> + <value value="0x64" name="FMT6_16_16_16_16_SINT"/> + + <value value="0x65" name="FMT6_32_32_UNORM"/> + <value value="0x66" name="FMT6_32_32_SNORM"/> + <value value="0x67" name="FMT6_32_32_FLOAT"/> + <value value="0x68" name="FMT6_32_32_UINT"/> + <value value="0x69" name="FMT6_32_32_SINT"/> + <value value="0x6a" name="FMT6_32_32_FIXED"/> + + <value value="0x70" name="FMT6_32_32_32_UNORM"/> + <value value="0x71" name="FMT6_32_32_32_SNORM"/> + <value value="0x72" name="FMT6_32_32_32_UINT"/> + <value value="0x73" name="FMT6_32_32_32_SINT"/> + <value value="0x74" name="FMT6_32_32_32_FLOAT"/> + <value value="0x75" name="FMT6_32_32_32_FIXED"/> + + <value value="0x80" name="FMT6_32_32_32_32_UNORM"/> + <value value="0x81" name="FMT6_32_32_32_32_SNORM"/> + <value value="0x82" name="FMT6_32_32_32_32_FLOAT"/> + <value value="0x83" name="FMT6_32_32_32_32_UINT"/> + <value value="0x84" name="FMT6_32_32_32_32_SINT"/> + <value value="0x85" name="FMT6_32_32_32_32_FIXED"/> + + <value value="0x8c" name="FMT6_G8R8B8R8_422_UNORM"/> <!-- UYVY --> + <value value="0x8d" name="FMT6_R8G8R8B8_422_UNORM"/> <!-- YUYV --> + <value value="0x8e" name="FMT6_R8_G8B8_2PLANE_420_UNORM"/> <!-- NV12 --> + <value value="0x8f" name="FMT6_NV21"/> + <value value="0x90" name="FMT6_R8_G8_B8_3PLANE_420_UNORM"/> <!-- YV12 --> + + <value value="0x91" name="FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8"/> + + <!-- Note: tiling/UBWC for these may be different from equivalent formats + For example FMT6_NV12_Y is not compatible with FMT6_8_UNORM + --> + <value value="0x94" name="FMT6_NV12_Y"/> + <value value="0x95" name="FMT6_NV12_UV"/> + <value value="0x96" name="FMT6_NV12_VU"/> + <value value="0x97" name="FMT6_NV12_4R"/> + <value value="0x98" name="FMT6_NV12_4R_Y"/> + <value value="0x99" name="FMT6_NV12_4R_UV"/> + <value value="0x9a" name="FMT6_P010"/> + <value value="0x9b" name="FMT6_P010_Y"/> + <value value="0x9c" name="FMT6_P010_UV"/> + <value value="0x9d" name="FMT6_TP10"/> + <value value="0x9e" name="FMT6_TP10_Y"/> + <value value="0x9f" name="FMT6_TP10_UV"/> + + <value value="0xa0" name="FMT6_Z24_UNORM_S8_UINT"/> + + <value value="0xab" name="FMT6_ETC2_RG11_UNORM"/> + <value value="0xac" name="FMT6_ETC2_RG11_SNORM"/> + <value value="0xad" name="FMT6_ETC2_R11_UNORM"/> + <value value="0xae" name="FMT6_ETC2_R11_SNORM"/> + <value value="0xaf" name="FMT6_ETC1"/> + <value value="0xb0" name="FMT6_ETC2_RGB8"/> + <value value="0xb1" name="FMT6_ETC2_RGBA8"/> + <value value="0xb2" name="FMT6_ETC2_RGB8A1"/> + <value value="0xb3" name="FMT6_DXT1"/> + <value value="0xb4" name="FMT6_DXT3"/> + <value value="0xb5" name="FMT6_DXT5"/> + <value value="0xb6" name="FMT6_RGTC1_UNORM"/> + <value value="0xb7" name="FMT6_RGTC1_UNORM_FAST"/> + <value value="0xb8" name="FMT6_RGTC1_SNORM"/> + <value value="0xb9" name="FMT6_RGTC1_SNORM_FAST"/> + <value value="0xba" name="FMT6_RGTC2_UNORM"/> + <value value="0xbb" name="FMT6_RGTC2_UNORM_FAST"/> + <value value="0xbc" name="FMT6_RGTC2_SNORM"/> + <value value="0xbd" name="FMT6_RGTC2_SNORM_FAST"/> + <value value="0xbe" name="FMT6_BPTC_UFLOAT"/> + <value value="0xbf" name="FMT6_BPTC_FLOAT"/> + <value value="0xc0" name="FMT6_BPTC"/> + <value value="0xc1" name="FMT6_ASTC_4x4"/> + <value value="0xc2" name="FMT6_ASTC_5x4"/> + <value value="0xc3" name="FMT6_ASTC_5x5"/> + <value value="0xc4" name="FMT6_ASTC_6x5"/> + <value value="0xc5" name="FMT6_ASTC_6x6"/> + <value value="0xc6" name="FMT6_ASTC_8x5"/> + <value value="0xc7" name="FMT6_ASTC_8x6"/> + <value value="0xc8" name="FMT6_ASTC_8x8"/> + <value value="0xc9" name="FMT6_ASTC_10x5"/> + <value value="0xca" name="FMT6_ASTC_10x6"/> + <value value="0xcb" name="FMT6_ASTC_10x8"/> + <value value="0xcc" name="FMT6_ASTC_10x10"/> + <value value="0xcd" name="FMT6_ASTC_12x10"/> + <value value="0xce" name="FMT6_ASTC_12x12"/> + + <!-- for sampling stencil (integer, 2nd channel), not available on a630 --> + <value value="0xea" name="FMT6_Z24_UINT_S8_UINT"/> + + <!-- Not a hw enum, used internally in driver --> + <value value="0xff" name="FMT6_NONE"/> + +</enum> + +<!-- probably same as a5xx --> +<enum name="a6xx_polygon_mode"> + <value name="POLYMODE6_POINTS" value="1"/> + <value name="POLYMODE6_LINES" value="2"/> + <value name="POLYMODE6_TRIANGLES" value="3"/> +</enum> + +<enum name="a6xx_depth_format"> + <value name="DEPTH6_NONE" value="0"/> + <value name="DEPTH6_16" value="1"/> + <value name="DEPTH6_24_8" value="2"/> + <value name="DEPTH6_32" value="4"/> +</enum> + +<bitset name="a6x_cp_protect" inline="yes"> + <bitfield name="BASE_ADDR" low="0" high="17"/> + <bitfield name="MASK_LEN" low="18" high="30"/> + <bitfield name="READ" pos="31" type="boolean"/> +</bitset> + +<enum name="a6xx_shader_id"> + <value value="0x9" name="A6XX_TP0_TMO_DATA"/> + <value value="0xa" name="A6XX_TP0_SMO_DATA"/> + <value value="0xb" name="A6XX_TP0_MIPMAP_BASE_DATA"/> + <value value="0x19" name="A6XX_TP1_TMO_DATA"/> + <value value="0x1a" name="A6XX_TP1_SMO_DATA"/> + <value value="0x1b" name="A6XX_TP1_MIPMAP_BASE_DATA"/> + <value value="0x29" name="A6XX_SP_INST_DATA"/> + <value value="0x2a" name="A6XX_SP_LB_0_DATA"/> + <value value="0x2b" name="A6XX_SP_LB_1_DATA"/> + <value value="0x2c" name="A6XX_SP_LB_2_DATA"/> + <value value="0x2d" name="A6XX_SP_LB_3_DATA"/> + <value value="0x2e" name="A6XX_SP_LB_4_DATA"/> + <value value="0x2f" name="A6XX_SP_LB_5_DATA"/> + <value value="0x30" name="A6XX_SP_CB_BINDLESS_DATA"/> + <value value="0x31" name="A6XX_SP_CB_LEGACY_DATA"/> + <value value="0x32" name="A6XX_SP_GFX_UAV_BASE_DATA"/> + <value value="0x33" name="A6XX_SP_INST_TAG"/> + <value value="0x34" name="A6XX_SP_CB_BINDLESS_TAG"/> + <value value="0x35" name="A6XX_SP_TMO_UMO_TAG"/> + <value value="0x36" name="A6XX_SP_SMO_TAG"/> + <value value="0x37" name="A6XX_SP_STATE_DATA"/> + <value value="0x49" name="A6XX_HLSQ_CHUNK_CVS_RAM"/> + <value value="0x4a" name="A6XX_HLSQ_CHUNK_CPS_RAM"/> + <value value="0x4b" name="A6XX_HLSQ_CHUNK_CVS_RAM_TAG"/> + <value value="0x4c" name="A6XX_HLSQ_CHUNK_CPS_RAM_TAG"/> + <value value="0x4d" name="A6XX_HLSQ_ICB_CVS_CB_BASE_TAG"/> + <value value="0x4e" name="A6XX_HLSQ_ICB_CPS_CB_BASE_TAG"/> + <value value="0x50" name="A6XX_HLSQ_CVS_MISC_RAM"/> + <value value="0x51" name="A6XX_HLSQ_CPS_MISC_RAM"/> + <value value="0x52" name="A6XX_HLSQ_INST_RAM"/> + <value value="0x53" name="A6XX_HLSQ_GFX_CVS_CONST_RAM"/> + <value value="0x54" name="A6XX_HLSQ_GFX_CPS_CONST_RAM"/> + <value value="0x55" name="A6XX_HLSQ_CVS_MISC_RAM_TAG"/> + <value value="0x56" name="A6XX_HLSQ_CPS_MISC_RAM_TAG"/> + <value value="0x57" name="A6XX_HLSQ_INST_RAM_TAG"/> + <value value="0x58" name="A6XX_HLSQ_GFX_CVS_CONST_RAM_TAG"/> + <value value="0x59" name="A6XX_HLSQ_GFX_CPS_CONST_RAM_TAG"/> + <value value="0x5a" name="A6XX_HLSQ_PWR_REST_RAM"/> + <value value="0x5b" name="A6XX_HLSQ_PWR_REST_TAG"/> + <value value="0x60" name="A6XX_HLSQ_DATAPATH_META"/> + <value value="0x61" name="A6XX_HLSQ_FRONTEND_META"/> + <value value="0x62" name="A6XX_HLSQ_INDIRECT_META"/> + <value value="0x63" name="A6XX_HLSQ_BACKEND_META"/> + <value value="0x70" name="A6XX_SP_LB_6_DATA"/> + <value value="0x71" name="A6XX_SP_LB_7_DATA"/> + <value value="0x73" name="A6XX_HLSQ_INST_RAM_1"/> +</enum> + +<enum name="a6xx_debugbus_id"> + <value value="0x1" name="A6XX_DBGBUS_CP"/> + <value value="0x2" name="A6XX_DBGBUS_RBBM"/> + <value value="0x3" name="A6XX_DBGBUS_VBIF"/> + <value value="0x4" name="A6XX_DBGBUS_HLSQ"/> + <value value="0x5" name="A6XX_DBGBUS_UCHE"/> + <value value="0x6" name="A6XX_DBGBUS_DPM"/> + <value value="0x7" name="A6XX_DBGBUS_TESS"/> + <value value="0x8" name="A6XX_DBGBUS_PC"/> + <value value="0x9" name="A6XX_DBGBUS_VFDP"/> + <value value="0xa" name="A6XX_DBGBUS_VPC"/> + <value value="0xb" name="A6XX_DBGBUS_TSE"/> + <value value="0xc" name="A6XX_DBGBUS_RAS"/> + <value value="0xd" name="A6XX_DBGBUS_VSC"/> + <value value="0xe" name="A6XX_DBGBUS_COM"/> + <value value="0x10" name="A6XX_DBGBUS_LRZ"/> + <value value="0x11" name="A6XX_DBGBUS_A2D"/> + <value value="0x12" name="A6XX_DBGBUS_CCUFCHE"/> + <value value="0x13" name="A6XX_DBGBUS_GMU_CX"/> + <value value="0x14" name="A6XX_DBGBUS_RBP"/> + <value value="0x15" name="A6XX_DBGBUS_DCS"/> + <value value="0x16" name="A6XX_DBGBUS_DBGC"/> + <value value="0x17" name="A6XX_DBGBUS_CX"/> + <value value="0x18" name="A6XX_DBGBUS_GMU_GX"/> + <value value="0x19" name="A6XX_DBGBUS_TPFCHE"/> + <value value="0x1a" name="A6XX_DBGBUS_GBIF_GX"/> + <value value="0x1d" name="A6XX_DBGBUS_GPC"/> + <value value="0x1e" name="A6XX_DBGBUS_LARC"/> + <value value="0x1f" name="A6XX_DBGBUS_HLSQ_SPTP"/> + <value value="0x20" name="A6XX_DBGBUS_RB_0"/> + <value value="0x21" name="A6XX_DBGBUS_RB_1"/> + <value value="0x22" name="A6XX_DBGBUS_RB_2"/> + <value value="0x24" name="A6XX_DBGBUS_UCHE_WRAPPER"/> + <value value="0x28" name="A6XX_DBGBUS_CCU_0"/> + <value value="0x29" name="A6XX_DBGBUS_CCU_1"/> + <value value="0x2a" name="A6XX_DBGBUS_CCU_2"/> + <value value="0x38" name="A6XX_DBGBUS_VFD_0"/> + <value value="0x39" name="A6XX_DBGBUS_VFD_1"/> + <value value="0x3a" name="A6XX_DBGBUS_VFD_2"/> + <value value="0x3b" name="A6XX_DBGBUS_VFD_3"/> + <value value="0x3c" name="A6XX_DBGBUS_VFD_4"/> + <value value="0x3d" name="A6XX_DBGBUS_VFD_5"/> + <value value="0x40" name="A6XX_DBGBUS_SP_0"/> + <value value="0x41" name="A6XX_DBGBUS_SP_1"/> + <value value="0x42" name="A6XX_DBGBUS_SP_2"/> + <value value="0x48" name="A6XX_DBGBUS_TPL1_0"/> + <value value="0x49" name="A6XX_DBGBUS_TPL1_1"/> + <value value="0x4a" name="A6XX_DBGBUS_TPL1_2"/> + <value value="0x4b" name="A6XX_DBGBUS_TPL1_3"/> + <value value="0x4c" name="A6XX_DBGBUS_TPL1_4"/> + <value value="0x4d" name="A6XX_DBGBUS_TPL1_5"/> + <value value="0x58" name="A6XX_DBGBUS_SPTP_0"/> + <value value="0x59" name="A6XX_DBGBUS_SPTP_1"/> + <value value="0x5a" name="A6XX_DBGBUS_SPTP_2"/> + <value value="0x5b" name="A6XX_DBGBUS_SPTP_3"/> + <value value="0x5c" name="A6XX_DBGBUS_SPTP_4"/> + <value value="0x5d" name="A6XX_DBGBUS_SPTP_5"/> +</enum> + +<!-- +Used in a6xx_a2d_blt_cntl.. the value mostly seems to correlate to the +component type/size, so I think it relates to internal format used for +blending? The one exception is that 16b unorm and 32b float use the +same value... maybe 16b unorm is uncommon enough that it was just easier +to upconvert to 32b float internally? + + 8b unorm: 10 (sometimes 0, is the high bit part of something else?) +16b unorm: 4 + +32b int: 7 +16b int: 6 + 8b int: 5 + +32b float: 4 +16b float: 3 + --> +<enum name="a6xx_2d_ifmt"> + <value value="0x7" name="R2D_INT32"/> + <value value="0x6" name="R2D_INT16"/> + <value value="0x5" name="R2D_INT8"/> + <value value="0x4" name="R2D_FLOAT32"/> + <value value="0x3" name="R2D_FLOAT16"/> + <value value="0x2" name="R2D_SNORM8"/> + <value value="0x1" name="R2D_UNORM8_SRGB"/> + <value value="0x0" name="R2D_UNORM8"/> +</enum> + +<enum name="a6xx_tex_type"> + <value name="A6XX_TEX_1D" value="0"/> + <value name="A6XX_TEX_2D" value="1"/> + <value name="A6XX_TEX_CUBE" value="2"/> + <value name="A6XX_TEX_3D" value="3"/> + <value name="A6XX_TEX_BUFFER" value="4"/> + <doc> + A special buffer type for usage as the source for buffer + to image copies with lower alignment requirements than + A6XX_TEX_2D, available since A7XX. + </doc> + <value name="A6XX_TEX_IMG_BUFFER" value="5"/> +</enum> + +<enum name="a6xx_ztest_mode"> + <doc>Allow early z-test and early-lrz (if applicable)</doc> + <value value="0x0" name="A6XX_EARLY_Z"/> + <doc>Disable early z-test and early-lrz test (if applicable)</doc> + <value value="0x1" name="A6XX_LATE_Z"/> + <doc> + A special mode that allows early-lrz (if applicable) or early-z + tests, but also does late-z tests at which point it writes depth. + + This mode is used when fragment can be killed (via discard or + sample mask) after early-z tests and it writes depth. In such case + depth can be written only at late-z stage, but it's ok to use + early-z to discard fragments. + + However this mode is not compatible with: + - Lack of D/S attachment + - Stencil writes on stencil or depth test failures + - Per-sample shading + </doc> + <value value="0x2" name="A6XX_EARLY_Z_LATE_Z"/> + <doc>Not a real hw value, used internally by mesa</doc> + <value value="0x3" name="A6XX_INVALID_ZTEST"/> +</enum> + +<enum name="a6xx_tess_spacing"> + <value value="0x0" name="TESS_EQUAL"/> + <value value="0x2" name="TESS_FRACTIONAL_ODD"/> + <value value="0x3" name="TESS_FRACTIONAL_EVEN"/> +</enum> +<enum name="a6xx_tess_output"> + <value value="0x0" name="TESS_POINTS"/> + <value value="0x1" name="TESS_LINES"/> + <value value="0x2" name="TESS_CW_TRIS"/> + <value value="0x3" name="TESS_CCW_TRIS"/> +</enum> + +<enum name="a6xx_tex_filter"> <!-- same as a4xx? --> + <value name="A6XX_TEX_NEAREST" value="0"/> + <value name="A6XX_TEX_LINEAR" value="1"/> + <value name="A6XX_TEX_ANISO" value="2"/> + <value name="A6XX_TEX_CUBIC" value="3"/> <!-- a650 only --> +</enum> + +<enum name="a6xx_tex_clamp"> <!-- same as a4xx? --> + <value name="A6XX_TEX_REPEAT" value="0"/> + <value name="A6XX_TEX_CLAMP_TO_EDGE" value="1"/> + <value name="A6XX_TEX_MIRROR_REPEAT" value="2"/> + <value name="A6XX_TEX_CLAMP_TO_BORDER" value="3"/> + <value name="A6XX_TEX_MIRROR_CLAMP" value="4"/> +</enum> + +<enum name="a6xx_tex_aniso"> <!-- same as a4xx? --> + <value name="A6XX_TEX_ANISO_1" value="0"/> + <value name="A6XX_TEX_ANISO_2" value="1"/> + <value name="A6XX_TEX_ANISO_4" value="2"/> + <value name="A6XX_TEX_ANISO_8" value="3"/> + <value name="A6XX_TEX_ANISO_16" value="4"/> +</enum> + +<enum name="a6xx_reduction_mode"> + <value name="A6XX_REDUCTION_MODE_AVERAGE" value="0"/> + <value name="A6XX_REDUCTION_MODE_MIN" value="1"/> + <value name="A6XX_REDUCTION_MODE_MAX" value="2"/> +</enum> + +<enum name="a6xx_fast_border_color"> + <!-- R B G A --> + <value name="A6XX_BORDER_COLOR_0_0_0_0" value="0"/> + <value name="A6XX_BORDER_COLOR_0_0_0_1" value="1"/> + <value name="A6XX_BORDER_COLOR_1_1_1_0" value="2"/> + <value name="A6XX_BORDER_COLOR_1_1_1_1" value="3"/> +</enum> + +<enum name="a6xx_tex_swiz"> <!-- same as a4xx? --> + <value name="A6XX_TEX_X" value="0"/> + <value name="A6XX_TEX_Y" value="1"/> + <value name="A6XX_TEX_Z" value="2"/> + <value name="A6XX_TEX_W" value="3"/> + <value name="A6XX_TEX_ZERO" value="4"/> + <value name="A6XX_TEX_ONE" value="5"/> +</enum> + +</database> diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml index 6531749d30f4..c4e00b1263cd 100644 --- a/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml +++ b/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml @@ -40,51 +40,62 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <bitfield name="IRQ_MASK_BIT" pos="0" /> </bitset> - <reg32 offset="0x80" name="GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL"/> - <reg32 offset="0x81" name="GMU_GX_SPTPRAC_POWER_CONTROL"/> - <reg32 offset="0xc00" name="GMU_CM3_ITCM_START"/> - <reg32 offset="0x1c00" name="GMU_CM3_DTCM_START"/> - <reg32 offset="0x23f0" name="GMU_NMI_CONTROL_STATUS"/> - <reg32 offset="0x23f8" name="GMU_BOOT_SLUMBER_OPTION"/> - <reg32 offset="0x23f9" name="GMU_GX_VOTE_IDX"/> - <reg32 offset="0x23fa" name="GMU_MX_VOTE_IDX"/> - <reg32 offset="0x23fc" name="GMU_DCVS_ACK_OPTION"/> - <reg32 offset="0x23fd" name="GMU_DCVS_PERF_SETTING"/> - <reg32 offset="0x23fe" name="GMU_DCVS_BW_SETTING"/> - <reg32 offset="0x23ff" name="GMU_DCVS_RETURN"/> - <reg32 offset="0x4c00" name="GMU_ICACHE_CONFIG"/> - <reg32 offset="0x4c01" name="GMU_DCACHE_CONFIG"/> - <reg32 offset="0x4c0f" name="GMU_SYS_BUS_CONFIG"/> - <reg32 offset="0x5000" name="GMU_CM3_SYSRESET"/> - <reg32 offset="0x5001" name="GMU_CM3_BOOT_CONFIG"/> - <reg32 offset="0x501a" name="GMU_CM3_FW_BUSY"/> - <reg32 offset="0x501c" name="GMU_CM3_FW_INIT_RESULT"/> - <reg32 offset="0x502d" name="GMU_CM3_CFG"/> - <reg32 offset="0x5040" name="GMU_CX_GMU_POWER_COUNTER_ENABLE"/> - <reg32 offset="0x5041" name="GMU_CX_GMU_POWER_COUNTER_SELECT_0"/> - <reg32 offset="0x5042" name="GMU_CX_GMU_POWER_COUNTER_SELECT_1"/> - <reg32 offset="0x5044" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L"/> - <reg32 offset="0x5045" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H"/> - <reg32 offset="0x5046" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_1_L"/> - <reg32 offset="0x5047" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_1_H"/> - <reg32 offset="0x5048" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_2_L"/> - <reg32 offset="0x5049" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_2_H"/> - <reg32 offset="0x504a" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_3_L"/> - <reg32 offset="0x504b" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_3_H"/> - <reg32 offset="0x504c" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_4_L"/> - <reg32 offset="0x504d" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_4_H"/> - <reg32 offset="0x504e" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_5_L"/> - <reg32 offset="0x504f" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_5_H"/> - <reg32 offset="0x50c0" name="GMU_PWR_COL_INTER_FRAME_CTRL"> + <reg32 offset="0x1a880" name="GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL"/> + <reg32 offset="0x1a881" name="GMU_GX_SPTPRAC_POWER_CONTROL"/> + <reg32 offset="0x1b400" name="GMU_CM3_ITCM_START"/> + <reg32 offset="0x1c400" name="GMU_CM3_DTCM_START"/> + <reg32 offset="0x1cbf0" name="GMU_NMI_CONTROL_STATUS"/> + <reg32 offset="0x1cbf8" name="GMU_BOOT_SLUMBER_OPTION"/> + <reg32 offset="0x1cbf9" name="GMU_GX_VOTE_IDX"/> + <reg32 offset="0x1cbfa" name="GMU_MX_VOTE_IDX"/> + <reg32 offset="0x1cbfc" name="GMU_DCVS_ACK_OPTION"/> + <reg32 offset="0x1cbfd" name="GMU_DCVS_PERF_SETTING"/> + <reg32 offset="0x1cbfe" name="GMU_DCVS_BW_SETTING"/> + <reg32 offset="0x1cbff" name="GMU_DCVS_RETURN"/> + <reg32 offset="0x1d3f8" name="GMU_CORE_FW_VERSION"> + <bitfield name="MAJOR" low="28" high="31"/> + <bitfield name="MINOR" low="16" high="27"/> + <bitfield name="STEP" low="0" high="15"/> + </reg32> + <reg32 offset="0x1f400" name="GMU_ICACHE_CONFIG"/> + <reg32 offset="0x1f401" name="GMU_DCACHE_CONFIG"/> + <reg32 offset="0x1f40f" name="GMU_SYS_BUS_CONFIG"/> + <reg32 offset="0x1f50b" name="GMU_MRC_GBIF_QOS_CTRL"/> + <reg32 offset="0x1f800" name="GMU_CM3_SYSRESET"/> + <reg32 offset="0x1f801" name="GMU_CM3_BOOT_CONFIG"/> + <reg32 offset="0x1f81a" name="GMU_CM3_FW_BUSY"/> + <reg32 offset="0x1f81c" name="GMU_CM3_FW_INIT_RESULT"/> + <reg32 offset="0x1f82d" name="GMU_CM3_CFG"/> + <reg32 offset="0x1f840" name="GMU_CX_GMU_POWER_COUNTER_ENABLE"/> + <reg32 offset="0x1fc10" name="GMU_CX_GMU_POWER_COUNTER_ENABLE" variants="A8XX"/> + <reg32 offset="0x1f841" name="GMU_CX_GMU_POWER_COUNTER_SELECT_0"/> + <reg32 offset="0x1f842" name="GMU_CX_GMU_POWER_COUNTER_SELECT_1"/> + <reg32 offset="0x1fc40" name="GMU_CX_GMU_POWER_COUNTER_SELECT_XOCLK_0" variants="A8XX-"/> + <reg32 offset="0x1fc41" name="GMU_CX_GMU_POWER_COUNTER_SELECT_XOCLK_1" variants="A8XX-"/> + <reg32 offset="0x1f844" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L"/> + <reg32 offset="0x1fca0" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L" variants="A8XX-"/> + <reg32 offset="0x1f845" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H"/> + <reg32 offset="0x1fca1" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H" variants="A8XX-"/> + <reg32 offset="0x1f846" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_1_L"/> + <reg32 offset="0x1f847" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_1_H"/> + <reg32 offset="0x1f848" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_2_L"/> + <reg32 offset="0x1f849" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_2_H"/> + <reg32 offset="0x1f84a" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_3_L"/> + <reg32 offset="0x1f84b" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_3_H"/> + <reg32 offset="0x1f84c" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_4_L"/> + <reg32 offset="0x1f84d" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_4_H"/> + <reg32 offset="0x1f84e" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_5_L"/> + <reg32 offset="0x1f84f" name="GMU_CX_GMU_POWER_COUNTER_XOCLK_5_H"/> + <reg32 offset="0x1f8c0" name="GMU_PWR_COL_INTER_FRAME_CTRL"> <bitfield name="IFPC_ENABLE" pos="0" type="boolean"/> <bitfield name="HM_POWER_COLLAPSE_ENABLE" pos="1" type="boolean"/> <bitfield name="SPTPRAC_POWER_CONTROL_ENABLE" pos="2" type="boolean"/> <bitfield name="NUM_PASS_SKIPS" low="10" high="13"/> <bitfield name="MIN_PASS_LENGTH" low="14" high="31"/> </reg32> - <reg32 offset="0x50c1" name="GMU_PWR_COL_INTER_FRAME_HYST"/> - <reg32 offset="0x50c2" name="GMU_PWR_COL_SPTPRAC_HYST"/> - <reg32 offset="0x50d0" name="GMU_SPTPRAC_PWR_CLK_STATUS"> + <reg32 offset="0x1f8c1" name="GMU_PWR_COL_INTER_FRAME_HYST"/> + <reg32 offset="0x1f8c2" name="GMU_PWR_COL_SPTPRAC_HYST"/> + <reg32 offset="0x1f8d0" name="GMU_SPTPRAC_PWR_CLK_STATUS" variants="A6XX"> <bitfield name="SPTPRAC_GDSC_POWERING_OFF" pos="0" type="boolean"/> <bitfield name="SPTPRAC_GDSC_POWERING_ON" pos="1" type="boolean"/> <bitfield name="SPTPRAC_GDSC_POWER_OFF" pos="2" type="boolean"/> @@ -94,11 +105,19 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <bitfield name="GX_HM_GDSC_POWER_OFF" pos="6" type="boolean"/> <bitfield name="GX_HM_CLK_OFF" pos="7" type="boolean"/> </reg32> - <reg32 offset="0x50e4" name="GMU_GPU_NAP_CTRL"> + <reg32 offset="0x1f8d0" name="GMU_SPTPRAC_PWR_CLK_STATUS" variants="A7XX"> + <bitfield name="GX_HM_GDSC_POWER_OFF" pos="0" type="boolean"/> + <bitfield name="GX_HM_CLK_OFF" pos="1" type="boolean"/> + </reg32> + <reg32 offset="0x1f7e8" name="GMU_PWR_CLK_STATUS" variants="A8XX-"> + <bitfield name="GX_HM_GDSC_POWER_OFF" pos="0" type="boolean"/> + <bitfield name="GX_HM_CLK_OFF" pos="1" type="boolean"/> + </reg32> + <reg32 offset="0x1f8e4" name="GMU_GPU_NAP_CTRL"> <bitfield name="HW_NAP_ENABLE" pos="0"/> <bitfield name="SID" low="4" high="8"/> </reg32> - <reg32 offset="0x50e8" name="GMU_RPMH_CTRL"> + <reg32 offset="0x1f8e8" name="GMU_RPMH_CTRL"> <bitfield name="RPMH_INTERFACE_ENABLE" pos="0" type="boolean"/> <bitfield name="LLC_VOTE_ENABLE" pos="4" type="boolean"/> <bitfield name="DDR_VOTE_ENABLE" pos="8" type="boolean"/> @@ -110,70 +129,84 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <bitfield name="CX_MIN_VOTE_ENABLE" pos="14" type="boolean"/> <bitfield name="GFX_MIN_VOTE_ENABLE" pos="15" type="boolean"/> </reg32> - <reg32 offset="0x50e9" name="GMU_RPMH_HYST_CTRL"/> - <reg32 offset="0x50ec" name="GPU_GMU_CX_GMU_RPMH_POWER_STATE"/> - <reg32 offset="0x50f0" name="GPU_GMU_CX_GMU_CX_FAL_INTF"/> - <reg32 offset="0x50f1" name="GPU_GMU_CX_GMU_CX_FALNEXT_INTF"/> - <reg32 offset="0x5100" name="GPU_GMU_CX_GMU_PWR_COL_CP_MSG"/> - <reg32 offset="0x5101" name="GPU_GMU_CX_GMU_PWR_COL_CP_RESP"/> - <reg32 offset="0x51f0" name="GMU_BOOT_KMD_LM_HANDSHAKE"/> - <reg32 offset="0x5157" name="GMU_LLM_GLM_SLEEP_CTRL"/> - <reg32 offset="0x5158" name="GMU_LLM_GLM_SLEEP_STATUS"/> - <reg32 offset="0x5088" name="GMU_ALWAYS_ON_COUNTER_L"/> - <reg32 offset="0x5089" name="GMU_ALWAYS_ON_COUNTER_H"/> - <reg32 offset="0x50c3" name="GMU_GMU_PWR_COL_KEEPALIVE"/> - <reg32 offset="0x5180" name="GMU_HFI_CTRL_STATUS"/> - <reg32 offset="0x5181" name="GMU_HFI_VERSION_INFO"/> - <reg32 offset="0x5182" name="GMU_HFI_SFR_ADDR"/> - <reg32 offset="0x5183" name="GMU_HFI_MMAP_ADDR"/> - <reg32 offset="0x5184" name="GMU_HFI_QTBL_INFO"/> - <reg32 offset="0x5185" name="GMU_HFI_QTBL_ADDR"/> - <reg32 offset="0x5186" name="GMU_HFI_CTRL_INIT"/> - <reg32 offset="0x5190" name="GMU_GMU2HOST_INTR_SET"/> - <reg32 offset="0x5191" name="GMU_GMU2HOST_INTR_CLR"/> - <reg32 offset="0x5192" name="GMU_GMU2HOST_INTR_INFO"> + <reg32 offset="0x1f8e9" name="GMU_RPMH_HYST_CTRL"/> + <reg32 offset="0x1f8ec" name="GPU_GMU_CX_GMU_RPMH_POWER_STATE" variants="A6XX"/> + <reg32 offset="0x1f7e9" name="GPU_GMU_CX_GMU_RPMH_POWER_STATE" variants="A8XX-"/> + <reg32 offset="0x1f8f0" name="GPU_GMU_CX_GMU_CX_FAL_INTF" variants="A6XX"/> + <reg32 offset="0x1f7ec" name="GPU_GMU_CX_GMU_CX_FAL_INTF" variants="A8XX-"/> + <reg32 offset="0x1f8f1" name="GPU_GMU_CX_GMU_CX_FALNEXT_INTF" variants="A6XX"/> + <reg32 offset="0x1f7ed" name="GPU_GMU_CX_GMU_CX_FALNEXT_INTF" variants="A8XX-"/> + <reg32 offset="0x1f900" name="GPU_GMU_CX_GMU_PWR_COL_CP_MSG"/> + <reg32 offset="0x1f901" name="GPU_GMU_CX_GMU_PWR_COL_CP_RESP"/> + <reg32 offset="0x1f9f0" name="GMU_BOOT_KMD_LM_HANDSHAKE"/> + <reg32 offset="0x1f957" name="GMU_LLM_GLM_SLEEP_CTRL"/> + <reg32 offset="0x1f958" name="GMU_LLM_GLM_SLEEP_STATUS"/> + <reg32 offset="0x1f888" name="GMU_ALWAYS_ON_COUNTER_L"/> + <reg32 offset="0x1f889" name="GMU_ALWAYS_ON_COUNTER_H"/> + <reg32 offset="0x1f8c3" name="GMU_GMU_PWR_COL_KEEPALIVE" variants="A6XX-A7XX"/> + <reg32 offset="0x1f7e4" name="GMU_GMU_PWR_COL_KEEPALIVE" variants="A8XX-"/> + <reg32 offset="0x1f8c4" name="GMU_PWR_COL_PREEMPT_KEEPALIVE" variants="A6XX-A7XX"/> + <reg32 offset="0x1f7e5" name="GMU_PWR_COL_PREEMPT_KEEPALIVE" variants="A8XX-"/> + <reg32 offset="0x1f980" name="GMU_HFI_CTRL_STATUS"/> + <reg32 offset="0x1f981" name="GMU_HFI_VERSION_INFO"/> + <reg32 offset="0x1f982" name="GMU_HFI_SFR_ADDR"/> + <reg32 offset="0x1f983" name="GMU_HFI_MMAP_ADDR"/> + <reg32 offset="0x1f984" name="GMU_HFI_QTBL_INFO"/> + <reg32 offset="0x1f985" name="GMU_HFI_QTBL_ADDR"/> + <reg32 offset="0x1f986" name="GMU_HFI_CTRL_INIT"/> + <reg32 offset="0x1f990" name="GMU_GMU2HOST_INTR_SET"/> + <reg32 offset="0x1f991" name="GMU_GMU2HOST_INTR_CLR"/> + <reg32 offset="0x1f992" name="GMU_GMU2HOST_INTR_INFO"> <bitfield name="MSGQ" pos="0" type="boolean"/> <bitfield name="CM3_FAULT" pos="23" type="boolean"/> </reg32> - <reg32 offset="0x5193" name="GMU_GMU2HOST_INTR_MASK"/> - <reg32 offset="0x5194" name="GMU_HOST2GMU_INTR_SET"/> - <reg32 offset="0x5195" name="GMU_HOST2GMU_INTR_CLR"/> - <reg32 offset="0x5196" name="GMU_HOST2GMU_INTR_RAW_INFO"/> - <reg32 offset="0x5197" name="GMU_HOST2GMU_INTR_EN_0"/> - <reg32 offset="0x5198" name="GMU_HOST2GMU_INTR_EN_1"/> - <reg32 offset="0x5199" name="GMU_HOST2GMU_INTR_EN_2"/> - <reg32 offset="0x519a" name="GMU_HOST2GMU_INTR_EN_3"/> - <reg32 offset="0x519b" name="GMU_HOST2GMU_INTR_INFO_0"/> - <reg32 offset="0x519c" name="GMU_HOST2GMU_INTR_INFO_1"/> - <reg32 offset="0x519d" name="GMU_HOST2GMU_INTR_INFO_2"/> - <reg32 offset="0x519e" name="GMU_HOST2GMU_INTR_INFO_3"/> - <reg32 offset="0x51c5" name="GMU_GENERAL_0"/> - <reg32 offset="0x51c6" name="GMU_GENERAL_1"/> - <reg32 offset="0x51cb" name="GMU_GENERAL_6"/> - <reg32 offset="0x51cc" name="GMU_GENERAL_7"/> - <reg32 offset="0x51cd" name="GMU_GENERAL_8" variants="A7XX"/> - <reg32 offset="0x51ce" name="GMU_GENERAL_9" variants="A7XX"/> - <reg32 offset="0x51cf" name="GMU_GENERAL_10" variants="A7XX"/> - <reg32 offset="0x515d" name="GMU_ISENSE_CTRL"/> - <reg32 offset="0x8920" name="GPU_CS_ENABLE_REG"/> - <reg32 offset="0x515d" name="GPU_GMU_CX_GMU_ISENSE_CTRL"/> - <reg32 offset="0x8578" name="GPU_CS_AMP_CALIBRATION_CONTROL3"/> - <reg32 offset="0x8558" name="GPU_CS_AMP_CALIBRATION_CONTROL2"/> - <reg32 offset="0x8580" name="GPU_CS_A_SENSOR_CTRL_0"/> - <reg32 offset="0x27ada" name="GPU_CS_A_SENSOR_CTRL_2"/> - <reg32 offset="0x881a" name="GPU_CS_SENSOR_GENERAL_STATUS"/> - <reg32 offset="0x8957" name="GPU_CS_AMP_CALIBRATION_CONTROL1"/> - <reg32 offset="0x881a" name="GPU_CS_SENSOR_GENERAL_STATUS"/> - <reg32 offset="0x881d" name="GPU_CS_AMP_CALIBRATION_STATUS1_0"/> - <reg32 offset="0x881f" name="GPU_CS_AMP_CALIBRATION_STATUS1_2"/> - <reg32 offset="0x8821" name="GPU_CS_AMP_CALIBRATION_STATUS1_4"/> - <reg32 offset="0x8965" name="GPU_CS_AMP_CALIBRATION_DONE"/> - <reg32 offset="0x896d" name="GPU_CS_AMP_PERIOD_CTRL"/> - <reg32 offset="0x8965" name="GPU_CS_AMP_CALIBRATION_DONE"/> - <reg32 offset="0x514d" name="GPU_GMU_CX_GMU_PWR_THRESHOLD"/> - <reg32 offset="0x9303" name="GMU_AO_INTERRUPT_EN"/> - <reg32 offset="0x9304" name="GMU_AO_HOST_INTERRUPT_CLR"/> - <reg32 offset="0x9305" name="GMU_AO_HOST_INTERRUPT_STATUS"> + <reg32 offset="0x1f993" name="GMU_GMU2HOST_INTR_MASK"/> + <reg32 offset="0x1f994" name="GMU_HOST2GMU_INTR_SET"/> + <reg32 offset="0x1f995" name="GMU_HOST2GMU_INTR_CLR"/> + <reg32 offset="0x1f996" name="GMU_HOST2GMU_INTR_RAW_INFO"/> + <reg32 offset="0x1f997" name="GMU_HOST2GMU_INTR_EN_0"/> + <reg32 offset="0x1f998" name="GMU_HOST2GMU_INTR_EN_1"/> + <reg32 offset="0x1f999" name="GMU_HOST2GMU_INTR_EN_2"/> + <reg32 offset="0x1f99a" name="GMU_HOST2GMU_INTR_EN_3"/> + <reg32 offset="0x1f99b" name="GMU_HOST2GMU_INTR_INFO_0"/> + <reg32 offset="0x1f99c" name="GMU_HOST2GMU_INTR_INFO_1"/> + <reg32 offset="0x1f99d" name="GMU_HOST2GMU_INTR_INFO_2"/> + <reg32 offset="0x1f99e" name="GMU_HOST2GMU_INTR_INFO_3"/> + <reg32 offset="0x1f9c5" name="GMU_GENERAL_0"/> + <reg32 offset="0x1f9c6" name="GMU_GENERAL_1"/> + <reg32 offset="0x1f9cb" name="GMU_GENERAL_6"/> + <reg32 offset="0x1f9cc" name="GMU_GENERAL_7"/> + <reg32 offset="0x1f9cd" name="GMU_GENERAL_8" variants="A7XX"/> + <reg32 offset="0x1f9ce" name="GMU_GENERAL_9" variants="A7XX"/> + <reg32 offset="0x1f9cf" name="GMU_GENERAL_10" variants="A7XX"/> + <reg32 offset="0x1f9c0" name="GMU_GENERAL_0" variants="A8XX"/> + <reg32 offset="0x1f9c1" name="GMU_GENERAL_1" variants="A8XX"/> + <reg32 offset="0x1f9c6" name="GMU_GENERAL_6" variants="A8XX"/> + <reg32 offset="0x1f9c7" name="GMU_GENERAL_7" variants="A8XX"/> + <reg32 offset="0x1f9c8" name="GMU_GENERAL_8" variants="A8XX"/> + <reg32 offset="0x1f9c9" name="GMU_GENERAL_9" variants="A8XX"/> + <reg32 offset="0x1f9ca" name="GMU_GENERAL_10" variants="A8XX"/> + <reg32 offset="0x1f9cb" name="GMU_GENERAL_11" variants="A8XX"/> + <reg32 offset="0x1f95d" name="GMU_ISENSE_CTRL"/> + <reg32 offset="0x23120" name="GPU_CS_ENABLE_REG"/> + <reg32 offset="0x1f95d" name="GPU_GMU_CX_GMU_ISENSE_CTRL"/> + <reg32 offset="0x22d78" name="GPU_CS_AMP_CALIBRATION_CONTROL3"/> + <reg32 offset="0x22d58" name="GPU_CS_AMP_CALIBRATION_CONTROL2"/> + <reg32 offset="0x22d80" name="GPU_CS_A_SENSOR_CTRL_0"/> + <reg32 offset="0x422da" name="GPU_CS_A_SENSOR_CTRL_2"/> + <reg32 offset="0x2301a" name="GPU_CS_SENSOR_GENERAL_STATUS"/> + <reg32 offset="0x23157" name="GPU_CS_AMP_CALIBRATION_CONTROL1"/> + <reg32 offset="0x2301a" name="GPU_CS_SENSOR_GENERAL_STATUS"/> + <reg32 offset="0x2301d" name="GPU_CS_AMP_CALIBRATION_STATUS1_0"/> + <reg32 offset="0x2301f" name="GPU_CS_AMP_CALIBRATION_STATUS1_2"/> + <reg32 offset="0x23021" name="GPU_CS_AMP_CALIBRATION_STATUS1_4"/> + <reg32 offset="0x23165" name="GPU_CS_AMP_CALIBRATION_DONE"/> + <reg32 offset="0x2316d" name="GPU_CS_AMP_PERIOD_CTRL"/> + <reg32 offset="0x23165" name="GPU_CS_AMP_CALIBRATION_DONE"/> + <reg32 offset="0x1f94d" name="GPU_GMU_CX_GMU_PWR_THRESHOLD"/> + <reg32 offset="0x23b03" name="GMU_AO_INTERRUPT_EN"/> + <reg32 offset="0x23b04" name="GMU_AO_HOST_INTERRUPT_CLR"/> + <reg32 offset="0x23b05" name="GMU_AO_HOST_INTERRUPT_STATUS"> <bitfield name="WDOG_BITE" pos="0" type="boolean"/> <bitfield name="RSCC_COMP" pos="1" type="boolean"/> <bitfield name="VDROOP" pos="2" type="boolean"/> @@ -181,27 +214,27 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <bitfield name="DBD_WAKEUP" pos="4" type="boolean"/> <bitfield name="HOST_AHB_BUS_ERROR" pos="5" type="boolean"/> </reg32> - <reg32 offset="0x9306" name="GMU_AO_HOST_INTERRUPT_MASK"/> - <reg32 offset="0x9309" name="GPU_GMU_AO_GMU_CGC_MODE_CNTL"/> - <reg32 offset="0x930a" name="GPU_GMU_AO_GMU_CGC_DELAY_CNTL"/> - <reg32 offset="0x930b" name="GPU_GMU_AO_GMU_CGC_HYST_CNTL"/> - <reg32 offset="0x930c" name="GPU_GMU_AO_GPU_CX_BUSY_STATUS"> + <reg32 offset="0x23b06" name="GMU_AO_HOST_INTERRUPT_MASK"/> + <reg32 offset="0x23b09" name="GPU_GMU_AO_GMU_CGC_MODE_CNTL"/> + <reg32 offset="0x23b0a" name="GPU_GMU_AO_GMU_CGC_DELAY_CNTL"/> + <reg32 offset="0x23b0b" name="GPU_GMU_AO_GMU_CGC_HYST_CNTL"/> + <reg32 offset="0x23b0c" name="GPU_GMU_AO_GPU_CX_BUSY_STATUS"> <bitfield name = "GPUBUSYIGNAHB" pos="23" type="boolean"/> </reg32> - <reg32 offset="0x930d" name="GPU_GMU_AO_GPU_CX_BUSY_STATUS2"/> - <reg32 offset="0x930e" name="GPU_GMU_AO_GPU_CX_BUSY_MASK"/> - <reg32 offset="0x9310" name="GMU_AO_AHB_FENCE_CTRL"/> - <reg32 offset="0x9313" name="GMU_AHB_FENCE_STATUS"/> - <reg32 offset="0x9314" name="GMU_AHB_FENCE_STATUS_CLR"/> - <reg32 offset="0x9315" name="GMU_RBBM_INT_UNMASKED_STATUS"/> - <reg32 offset="0x9316" name="GMU_AO_SPARE_CNTL"/> - <reg32 offset="0x9307" name="GMU_RSCC_CONTROL_REQ"/> - <reg32 offset="0x9308" name="GMU_RSCC_CONTROL_ACK"/> - <reg32 offset="0x9311" name="GMU_AHB_FENCE_RANGE_0"/> - <reg32 offset="0x9312" name="GMU_AHB_FENCE_RANGE_1"/> - <reg32 offset="0x9c03" name="GPU_CC_GX_GDSCR"/> - <reg32 offset="0x9d42" name="GPU_CC_GX_DOMAIN_MISC"/> - <reg32 offset="0xc001" name="GPU_CPR_FSM_CTL"/> + <reg32 offset="0x23b0d" name="GPU_GMU_AO_GPU_CX_BUSY_STATUS2"/> + <reg32 offset="0x23b0e" name="GPU_GMU_AO_GPU_CX_BUSY_MASK"/> + <reg32 offset="0x23b10" name="GMU_AO_AHB_FENCE_CTRL"/> + <reg32 offset="0x23b13" name="GMU_AHB_FENCE_STATUS"/> + <reg32 offset="0x23b14" name="GMU_AHB_FENCE_STATUS_CLR"/> + <reg32 offset="0x23b15" name="GMU_RBBM_INT_UNMASKED_STATUS"/> + <reg32 offset="0x23b16" name="GMU_AO_SPARE_CNTL"/> + <reg32 offset="0x23b07" name="GMU_RSCC_CONTROL_REQ"/> + <reg32 offset="0x23b08" name="GMU_RSCC_CONTROL_ACK"/> + <reg32 offset="0x23b11" name="GMU_AHB_FENCE_RANGE_0"/> + <reg32 offset="0x23b12" name="GMU_AHB_FENCE_RANGE_1"/> + <reg32 offset="0x24403" name="GPU_CC_GX_GDSCR"/> + <reg32 offset="0x24542" name="GPU_CC_GX_DOMAIN_MISC"/> + <reg32 offset="0x26801" name="GPU_CPR_FSM_CTL"/> <!-- starts at offset 0x8c00 on most gpus --> <reg32 offset="0x0004" name="GPU_RSCC_RSC_STATUS0_DRV0"/> @@ -223,6 +256,12 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <reg32 offset="0x03ee" name="RSCC_TCS1_DRV0_STATUS"/> <reg32 offset="0x0496" name="RSCC_TCS2_DRV0_STATUS"/> <reg32 offset="0x053e" name="RSCC_TCS3_DRV0_STATUS"/> + <reg32 offset="0x05e6" name="RSCC_TCS4_DRV0_STATUS" variants="A7XX-"/> + <reg32 offset="0x068e" name="RSCC_TCS5_DRV0_STATUS" variants="A7XX-"/> + <reg32 offset="0x0736" name="RSCC_TCS6_DRV0_STATUS" variants="A7XX-"/> + <reg32 offset="0x07de" name="RSCC_TCS7_DRV0_STATUS" variants="A7XX-"/> + <reg32 offset="0x0886" name="RSCC_TCS8_DRV0_STATUS" variants="A7XX-"/> + <reg32 offset="0x092e" name="RSCC_TCS9_DRV0_STATUS" variants="A7XX-"/> </domain> </database> diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx_perfcntrs.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx_perfcntrs.xml new file mode 100644 index 000000000000..c446a2eb1120 --- /dev/null +++ b/drivers/gpu/drm/msm/registers/adreno/a6xx_perfcntrs.xml @@ -0,0 +1,600 @@ +<?xml version="1.0" encoding="UTF-8"?> +<database xmlns="http://nouveau.freedesktop.org/" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> +<import file="freedreno_copyright.xml"/> +<import file="adreno/adreno_common.xml"/> +<import file="adreno/adreno_pm4.xml"/> + +<enum name="a6xx_cp_perfcounter_select"> + <value value="0" name="PERF_CP_ALWAYS_COUNT"/> + <value value="1" name="PERF_CP_BUSY_GFX_CORE_IDLE"/> + <value value="2" name="PERF_CP_BUSY_CYCLES"/> + <value value="3" name="PERF_CP_NUM_PREEMPTIONS"/> + <value value="4" name="PERF_CP_PREEMPTION_REACTION_DELAY"/> + <value value="5" name="PERF_CP_PREEMPTION_SWITCH_OUT_TIME"/> + <value value="6" name="PERF_CP_PREEMPTION_SWITCH_IN_TIME"/> + <value value="7" name="PERF_CP_DEAD_DRAWS_IN_BIN_RENDER"/> + <value value="8" name="PERF_CP_PREDICATED_DRAWS_KILLED"/> + <value value="9" name="PERF_CP_MODE_SWITCH"/> + <value value="10" name="PERF_CP_ZPASS_DONE"/> + <value value="11" name="PERF_CP_CONTEXT_DONE"/> + <value value="12" name="PERF_CP_CACHE_FLUSH"/> + <value value="13" name="PERF_CP_LONG_PREEMPTIONS"/> + <value value="14" name="PERF_CP_SQE_I_CACHE_STARVE"/> + <value value="15" name="PERF_CP_SQE_IDLE"/> + <value value="16" name="PERF_CP_SQE_PM4_STARVE_RB_IB"/> + <value value="17" name="PERF_CP_SQE_PM4_STARVE_SDS"/> + <value value="18" name="PERF_CP_SQE_MRB_STARVE"/> + <value value="19" name="PERF_CP_SQE_RRB_STARVE"/> + <value value="20" name="PERF_CP_SQE_VSD_STARVE"/> + <value value="21" name="PERF_CP_VSD_DECODE_STARVE"/> + <value value="22" name="PERF_CP_SQE_PIPE_OUT_STALL"/> + <value value="23" name="PERF_CP_SQE_SYNC_STALL"/> + <value value="24" name="PERF_CP_SQE_PM4_WFI_STALL"/> + <value value="25" name="PERF_CP_SQE_SYS_WFI_STALL"/> + <value value="26" name="PERF_CP_SQE_T4_EXEC"/> + <value value="27" name="PERF_CP_SQE_LOAD_STATE_EXEC"/> + <value value="28" name="PERF_CP_SQE_SAVE_SDS_STATE"/> + <value value="29" name="PERF_CP_SQE_DRAW_EXEC"/> + <value value="30" name="PERF_CP_SQE_CTXT_REG_BUNCH_EXEC"/> + <value value="31" name="PERF_CP_SQE_EXEC_PROFILED"/> + <value value="32" name="PERF_CP_MEMORY_POOL_EMPTY"/> + <value value="33" name="PERF_CP_MEMORY_POOL_SYNC_STALL"/> + <value value="34" name="PERF_CP_MEMORY_POOL_ABOVE_THRESH"/> + <value value="35" name="PERF_CP_AHB_WR_STALL_PRE_DRAWS"/> + <value value="36" name="PERF_CP_AHB_STALL_SQE_GMU"/> + <value value="37" name="PERF_CP_AHB_STALL_SQE_WR_OTHER"/> + <value value="38" name="PERF_CP_AHB_STALL_SQE_RD_OTHER"/> + <value value="39" name="PERF_CP_CLUSTER0_EMPTY"/> + <value value="40" name="PERF_CP_CLUSTER1_EMPTY"/> + <value value="41" name="PERF_CP_CLUSTER2_EMPTY"/> + <value value="42" name="PERF_CP_CLUSTER3_EMPTY"/> + <value value="43" name="PERF_CP_CLUSTER4_EMPTY"/> + <value value="44" name="PERF_CP_CLUSTER5_EMPTY"/> + <value value="45" name="PERF_CP_PM4_DATA"/> + <value value="46" name="PERF_CP_PM4_HEADERS"/> + <value value="47" name="PERF_CP_VBIF_READ_BEATS"/> + <value value="48" name="PERF_CP_VBIF_WRITE_BEATS"/> + <value value="49" name="PERF_CP_SQE_INSTR_COUNTER"/> +</enum> + +<enum name="a6xx_rbbm_perfcounter_select"> + <value value="0" name="PERF_RBBM_ALWAYS_COUNT"/> + <value value="1" name="PERF_RBBM_ALWAYS_ON"/> + <value value="2" name="PERF_RBBM_TSE_BUSY"/> + <value value="3" name="PERF_RBBM_RAS_BUSY"/> + <value value="4" name="PERF_RBBM_PC_DCALL_BUSY"/> + <value value="5" name="PERF_RBBM_PC_VSD_BUSY"/> + <value value="6" name="PERF_RBBM_STATUS_MASKED"/> + <value value="7" name="PERF_RBBM_COM_BUSY"/> + <value value="8" name="PERF_RBBM_DCOM_BUSY"/> + <value value="9" name="PERF_RBBM_VBIF_BUSY"/> + <value value="10" name="PERF_RBBM_VSC_BUSY"/> + <value value="11" name="PERF_RBBM_TESS_BUSY"/> + <value value="12" name="PERF_RBBM_UCHE_BUSY"/> + <value value="13" name="PERF_RBBM_HLSQ_BUSY"/> +</enum> + +<enum name="a6xx_pc_perfcounter_select"> + <value value="0" name="PERF_PC_BUSY_CYCLES"/> + <value value="1" name="PERF_PC_WORKING_CYCLES"/> + <value value="2" name="PERF_PC_STALL_CYCLES_VFD"/> + <value value="3" name="PERF_PC_STALL_CYCLES_TSE"/> + <value value="4" name="PERF_PC_STALL_CYCLES_VPC"/> + <value value="5" name="PERF_PC_STALL_CYCLES_UCHE"/> + <value value="6" name="PERF_PC_STALL_CYCLES_TESS"/> + <value value="7" name="PERF_PC_STALL_CYCLES_TSE_ONLY"/> + <value value="8" name="PERF_PC_STALL_CYCLES_VPC_ONLY"/> + <value value="9" name="PERF_PC_PASS1_TF_STALL_CYCLES"/> + <value value="10" name="PERF_PC_STARVE_CYCLES_FOR_INDEX"/> + <value value="11" name="PERF_PC_STARVE_CYCLES_FOR_TESS_FACTOR"/> + <value value="12" name="PERF_PC_STARVE_CYCLES_FOR_VIZ_STREAM"/> + <value value="13" name="PERF_PC_STARVE_CYCLES_FOR_POSITION"/> + <value value="14" name="PERF_PC_STARVE_CYCLES_DI"/> + <value value="15" name="PERF_PC_VIS_STREAMS_LOADED"/> + <value value="16" name="PERF_PC_INSTANCES"/> + <value value="17" name="PERF_PC_VPC_PRIMITIVES"/> + <value value="18" name="PERF_PC_DEAD_PRIM"/> + <value value="19" name="PERF_PC_LIVE_PRIM"/> + <value value="20" name="PERF_PC_VERTEX_HITS"/> + <value value="21" name="PERF_PC_IA_VERTICES"/> + <value value="22" name="PERF_PC_IA_PRIMITIVES"/> + <value value="23" name="PERF_PC_GS_PRIMITIVES"/> + <value value="24" name="PERF_PC_HS_INVOCATIONS"/> + <value value="25" name="PERF_PC_DS_INVOCATIONS"/> + <value value="26" name="PERF_PC_VS_INVOCATIONS"/> + <value value="27" name="PERF_PC_GS_INVOCATIONS"/> + <value value="28" name="PERF_PC_DS_PRIMITIVES"/> + <value value="29" name="PERF_PC_VPC_POS_DATA_TRANSACTION"/> + <value value="30" name="PERF_PC_3D_DRAWCALLS"/> + <value value="31" name="PERF_PC_2D_DRAWCALLS"/> + <value value="32" name="PERF_PC_NON_DRAWCALL_GLOBAL_EVENTS"/> + <value value="33" name="PERF_TESS_BUSY_CYCLES"/> + <value value="34" name="PERF_TESS_WORKING_CYCLES"/> + <value value="35" name="PERF_TESS_STALL_CYCLES_PC"/> + <value value="36" name="PERF_TESS_STARVE_CYCLES_PC"/> + <value value="37" name="PERF_PC_TSE_TRANSACTION"/> + <value value="38" name="PERF_PC_TSE_VERTEX"/> + <value value="39" name="PERF_PC_TESS_PC_UV_TRANS"/> + <value value="40" name="PERF_PC_TESS_PC_UV_PATCHES"/> + <value value="41" name="PERF_PC_TESS_FACTOR_TRANS"/> +</enum> + +<enum name="a6xx_vfd_perfcounter_select"> + <value value="0" name="PERF_VFD_BUSY_CYCLES"/> + <value value="1" name="PERF_VFD_STALL_CYCLES_UCHE"/> + <value value="2" name="PERF_VFD_STALL_CYCLES_VPC_ALLOC"/> + <value value="3" name="PERF_VFD_STALL_CYCLES_SP_INFO"/> + <value value="4" name="PERF_VFD_STALL_CYCLES_SP_ATTR"/> + <value value="5" name="PERF_VFD_STARVE_CYCLES_UCHE"/> + <value value="6" name="PERF_VFD_RBUFFER_FULL"/> + <value value="7" name="PERF_VFD_ATTR_INFO_FIFO_FULL"/> + <value value="8" name="PERF_VFD_DECODED_ATTRIBUTE_BYTES"/> + <value value="9" name="PERF_VFD_NUM_ATTRIBUTES"/> + <value value="10" name="PERF_VFD_UPPER_SHADER_FIBERS"/> + <value value="11" name="PERF_VFD_LOWER_SHADER_FIBERS"/> + <value value="12" name="PERF_VFD_MODE_0_FIBERS"/> + <value value="13" name="PERF_VFD_MODE_1_FIBERS"/> + <value value="14" name="PERF_VFD_MODE_2_FIBERS"/> + <value value="15" name="PERF_VFD_MODE_3_FIBERS"/> + <value value="16" name="PERF_VFD_MODE_4_FIBERS"/> + <value value="17" name="PERF_VFD_TOTAL_VERTICES"/> + <value value="18" name="PERF_VFDP_STALL_CYCLES_VFD"/> + <value value="19" name="PERF_VFDP_STALL_CYCLES_VFD_INDEX"/> + <value value="20" name="PERF_VFDP_STALL_CYCLES_VFD_PROG"/> + <value value="21" name="PERF_VFDP_STARVE_CYCLES_PC"/> + <value value="22" name="PERF_VFDP_VS_STAGE_WAVES"/> +</enum> + +<enum name="a6xx_hlsq_perfcounter_select"> + <value value="0" name="PERF_HLSQ_BUSY_CYCLES"/> + <value value="1" name="PERF_HLSQ_STALL_CYCLES_UCHE"/> + <value value="2" name="PERF_HLSQ_STALL_CYCLES_SP_STATE"/> + <value value="3" name="PERF_HLSQ_STALL_CYCLES_SP_FS_STAGE"/> + <value value="4" name="PERF_HLSQ_UCHE_LATENCY_CYCLES"/> + <value value="5" name="PERF_HLSQ_UCHE_LATENCY_COUNT"/> + <value value="6" name="PERF_HLSQ_FS_STAGE_1X_WAVES"/> + <value value="7" name="PERF_HLSQ_FS_STAGE_2X_WAVES"/> + <value value="8" name="PERF_HLSQ_QUADS"/> + <value value="9" name="PERF_HLSQ_CS_INVOCATIONS"/> + <value value="10" name="PERF_HLSQ_COMPUTE_DRAWCALLS"/> + <value value="11" name="PERF_HLSQ_FS_DATA_WAIT_PROGRAMMING"/> + <value value="12" name="PERF_HLSQ_DUAL_FS_PROG_ACTIVE"/> + <value value="13" name="PERF_HLSQ_DUAL_VS_PROG_ACTIVE"/> + <value value="14" name="PERF_HLSQ_FS_BATCH_COUNT_ZERO"/> + <value value="15" name="PERF_HLSQ_VS_BATCH_COUNT_ZERO"/> + <value value="16" name="PERF_HLSQ_WAVE_PENDING_NO_QUAD"/> + <value value="17" name="PERF_HLSQ_WAVE_PENDING_NO_PRIM_BASE"/> + <value value="18" name="PERF_HLSQ_STALL_CYCLES_VPC"/> + <value value="19" name="PERF_HLSQ_PIXELS"/> + <value value="20" name="PERF_HLSQ_DRAW_MODE_SWITCH_VSFS_SYNC"/> +</enum> + +<enum name="a6xx_vpc_perfcounter_select"> + <value value="0" name="PERF_VPC_BUSY_CYCLES"/> + <value value="1" name="PERF_VPC_WORKING_CYCLES"/> + <value value="2" name="PERF_VPC_STALL_CYCLES_UCHE"/> + <value value="3" name="PERF_VPC_STALL_CYCLES_VFD_WACK"/> + <value value="4" name="PERF_VPC_STALL_CYCLES_HLSQ_PRIM_ALLOC"/> + <value value="5" name="PERF_VPC_STALL_CYCLES_PC"/> + <value value="6" name="PERF_VPC_STALL_CYCLES_SP_LM"/> + <value value="7" name="PERF_VPC_STARVE_CYCLES_SP"/> + <value value="8" name="PERF_VPC_STARVE_CYCLES_LRZ"/> + <value value="9" name="PERF_VPC_PC_PRIMITIVES"/> + <value value="10" name="PERF_VPC_SP_COMPONENTS"/> + <value value="11" name="PERF_VPC_STALL_CYCLES_VPCRAM_POS"/> + <value value="12" name="PERF_VPC_LRZ_ASSIGN_PRIMITIVES"/> + <value value="13" name="PERF_VPC_RB_VISIBLE_PRIMITIVES"/> + <value value="14" name="PERF_VPC_LM_TRANSACTION"/> + <value value="15" name="PERF_VPC_STREAMOUT_TRANSACTION"/> + <value value="16" name="PERF_VPC_VS_BUSY_CYCLES"/> + <value value="17" name="PERF_VPC_PS_BUSY_CYCLES"/> + <value value="18" name="PERF_VPC_VS_WORKING_CYCLES"/> + <value value="19" name="PERF_VPC_PS_WORKING_CYCLES"/> + <value value="20" name="PERF_VPC_STARVE_CYCLES_RB"/> + <value value="21" name="PERF_VPC_NUM_VPCRAM_READ_POS"/> + <value value="22" name="PERF_VPC_WIT_FULL_CYCLES"/> + <value value="23" name="PERF_VPC_VPCRAM_FULL_CYCLES"/> + <value value="24" name="PERF_VPC_LM_FULL_WAIT_FOR_INTP_END"/> + <value value="25" name="PERF_VPC_NUM_VPCRAM_WRITE"/> + <value value="26" name="PERF_VPC_NUM_VPCRAM_READ_SO"/> + <value value="27" name="PERF_VPC_NUM_ATTR_REQ_LM"/> +</enum> + +<enum name="a6xx_tse_perfcounter_select"> + <value value="0" name="PERF_TSE_BUSY_CYCLES"/> + <value value="1" name="PERF_TSE_CLIPPING_CYCLES"/> + <value value="2" name="PERF_TSE_STALL_CYCLES_RAS"/> + <value value="3" name="PERF_TSE_STALL_CYCLES_LRZ_BARYPLANE"/> + <value value="4" name="PERF_TSE_STALL_CYCLES_LRZ_ZPLANE"/> + <value value="5" name="PERF_TSE_STARVE_CYCLES_PC"/> + <value value="6" name="PERF_TSE_INPUT_PRIM"/> + <value value="7" name="PERF_TSE_INPUT_NULL_PRIM"/> + <value value="8" name="PERF_TSE_TRIVAL_REJ_PRIM"/> + <value value="9" name="PERF_TSE_CLIPPED_PRIM"/> + <value value="10" name="PERF_TSE_ZERO_AREA_PRIM"/> + <value value="11" name="PERF_TSE_FACENESS_CULLED_PRIM"/> + <value value="12" name="PERF_TSE_ZERO_PIXEL_PRIM"/> + <value value="13" name="PERF_TSE_OUTPUT_NULL_PRIM"/> + <value value="14" name="PERF_TSE_OUTPUT_VISIBLE_PRIM"/> + <value value="15" name="PERF_TSE_CINVOCATION"/> + <value value="16" name="PERF_TSE_CPRIMITIVES"/> + <value value="17" name="PERF_TSE_2D_INPUT_PRIM"/> + <value value="18" name="PERF_TSE_2D_ALIVE_CYCLES"/> + <value value="19" name="PERF_TSE_CLIP_PLANES"/> +</enum> + +<enum name="a6xx_ras_perfcounter_select"> + <value value="0" name="PERF_RAS_BUSY_CYCLES"/> + <value value="1" name="PERF_RAS_SUPERTILE_ACTIVE_CYCLES"/> + <value value="2" name="PERF_RAS_STALL_CYCLES_LRZ"/> + <value value="3" name="PERF_RAS_STARVE_CYCLES_TSE"/> + <value value="4" name="PERF_RAS_SUPER_TILES"/> + <value value="5" name="PERF_RAS_8X4_TILES"/> + <value value="6" name="PERF_RAS_MASKGEN_ACTIVE"/> + <value value="7" name="PERF_RAS_FULLY_COVERED_SUPER_TILES"/> + <value value="8" name="PERF_RAS_FULLY_COVERED_8X4_TILES"/> + <value value="9" name="PERF_RAS_PRIM_KILLED_INVISILBE"/> + <value value="10" name="PERF_RAS_SUPERTILE_GEN_ACTIVE_CYCLES"/> + <value value="11" name="PERF_RAS_LRZ_INTF_WORKING_CYCLES"/> + <value value="12" name="PERF_RAS_BLOCKS"/> +</enum> + +<enum name="a6xx_uche_perfcounter_select"> + <value value="0" name="PERF_UCHE_BUSY_CYCLES"/> + <value value="1" name="PERF_UCHE_STALL_CYCLES_ARBITER"/> + <value value="2" name="PERF_UCHE_VBIF_LATENCY_CYCLES"/> + <value value="3" name="PERF_UCHE_VBIF_LATENCY_SAMPLES"/> + <value value="4" name="PERF_UCHE_VBIF_READ_BEATS_TP"/> + <value value="5" name="PERF_UCHE_VBIF_READ_BEATS_VFD"/> + <value value="6" name="PERF_UCHE_VBIF_READ_BEATS_HLSQ"/> + <value value="7" name="PERF_UCHE_VBIF_READ_BEATS_LRZ"/> + <value value="8" name="PERF_UCHE_VBIF_READ_BEATS_SP"/> + <value value="9" name="PERF_UCHE_READ_REQUESTS_TP"/> + <value value="10" name="PERF_UCHE_READ_REQUESTS_VFD"/> + <value value="11" name="PERF_UCHE_READ_REQUESTS_HLSQ"/> + <value value="12" name="PERF_UCHE_READ_REQUESTS_LRZ"/> + <value value="13" name="PERF_UCHE_READ_REQUESTS_SP"/> + <value value="14" name="PERF_UCHE_WRITE_REQUESTS_LRZ"/> + <value value="15" name="PERF_UCHE_WRITE_REQUESTS_SP"/> + <value value="16" name="PERF_UCHE_WRITE_REQUESTS_VPC"/> + <value value="17" name="PERF_UCHE_WRITE_REQUESTS_VSC"/> + <value value="18" name="PERF_UCHE_EVICTS"/> + <value value="19" name="PERF_UCHE_BANK_REQ0"/> + <value value="20" name="PERF_UCHE_BANK_REQ1"/> + <value value="21" name="PERF_UCHE_BANK_REQ2"/> + <value value="22" name="PERF_UCHE_BANK_REQ3"/> + <value value="23" name="PERF_UCHE_BANK_REQ4"/> + <value value="24" name="PERF_UCHE_BANK_REQ5"/> + <value value="25" name="PERF_UCHE_BANK_REQ6"/> + <value value="26" name="PERF_UCHE_BANK_REQ7"/> + <value value="27" name="PERF_UCHE_VBIF_READ_BEATS_CH0"/> + <value value="28" name="PERF_UCHE_VBIF_READ_BEATS_CH1"/> + <value value="29" name="PERF_UCHE_GMEM_READ_BEATS"/> + <value value="30" name="PERF_UCHE_TPH_REF_FULL"/> + <value value="31" name="PERF_UCHE_TPH_VICTIM_FULL"/> + <value value="32" name="PERF_UCHE_TPH_EXT_FULL"/> + <value value="33" name="PERF_UCHE_VBIF_STALL_WRITE_DATA"/> + <value value="34" name="PERF_UCHE_DCMP_LATENCY_SAMPLES"/> + <value value="35" name="PERF_UCHE_DCMP_LATENCY_CYCLES"/> + <value value="36" name="PERF_UCHE_VBIF_READ_BEATS_PC"/> + <value value="37" name="PERF_UCHE_READ_REQUESTS_PC"/> + <value value="38" name="PERF_UCHE_RAM_READ_REQ"/> + <value value="39" name="PERF_UCHE_RAM_WRITE_REQ"/> +</enum> + +<enum name="a6xx_tp_perfcounter_select"> + <value value="0" name="PERF_TP_BUSY_CYCLES"/> + <value value="1" name="PERF_TP_STALL_CYCLES_UCHE"/> + <value value="2" name="PERF_TP_LATENCY_CYCLES"/> + <value value="3" name="PERF_TP_LATENCY_TRANS"/> + <value value="4" name="PERF_TP_FLAG_CACHE_REQUEST_SAMPLES"/> + <value value="5" name="PERF_TP_FLAG_CACHE_REQUEST_LATENCY"/> + <value value="6" name="PERF_TP_L1_CACHELINE_REQUESTS"/> + <value value="7" name="PERF_TP_L1_CACHELINE_MISSES"/> + <value value="8" name="PERF_TP_SP_TP_TRANS"/> + <value value="9" name="PERF_TP_TP_SP_TRANS"/> + <value value="10" name="PERF_TP_OUTPUT_PIXELS"/> + <value value="11" name="PERF_TP_FILTER_WORKLOAD_16BIT"/> + <value value="12" name="PERF_TP_FILTER_WORKLOAD_32BIT"/> + <value value="13" name="PERF_TP_QUADS_RECEIVED"/> + <value value="14" name="PERF_TP_QUADS_OFFSET"/> + <value value="15" name="PERF_TP_QUADS_SHADOW"/> + <value value="16" name="PERF_TP_QUADS_ARRAY"/> + <value value="17" name="PERF_TP_QUADS_GRADIENT"/> + <value value="18" name="PERF_TP_QUADS_1D"/> + <value value="19" name="PERF_TP_QUADS_2D"/> + <value value="20" name="PERF_TP_QUADS_BUFFER"/> + <value value="21" name="PERF_TP_QUADS_3D"/> + <value value="22" name="PERF_TP_QUADS_CUBE"/> + <value value="23" name="PERF_TP_DIVERGENT_QUADS_RECEIVED"/> + <value value="24" name="PERF_TP_PRT_NON_RESIDENT_EVENTS"/> + <value value="25" name="PERF_TP_OUTPUT_PIXELS_POINT"/> + <value value="26" name="PERF_TP_OUTPUT_PIXELS_BILINEAR"/> + <value value="27" name="PERF_TP_OUTPUT_PIXELS_MIP"/> + <value value="28" name="PERF_TP_OUTPUT_PIXELS_ANISO"/> + <value value="29" name="PERF_TP_OUTPUT_PIXELS_ZERO_LOD"/> + <value value="30" name="PERF_TP_FLAG_CACHE_REQUESTS"/> + <value value="31" name="PERF_TP_FLAG_CACHE_MISSES"/> + <value value="32" name="PERF_TP_L1_5_L2_REQUESTS"/> + <value value="33" name="PERF_TP_2D_OUTPUT_PIXELS"/> + <value value="34" name="PERF_TP_2D_OUTPUT_PIXELS_POINT"/> + <value value="35" name="PERF_TP_2D_OUTPUT_PIXELS_BILINEAR"/> + <value value="36" name="PERF_TP_2D_FILTER_WORKLOAD_16BIT"/> + <value value="37" name="PERF_TP_2D_FILTER_WORKLOAD_32BIT"/> + <value value="38" name="PERF_TP_TPA2TPC_TRANS"/> + <value value="39" name="PERF_TP_L1_MISSES_ASTC_1TILE"/> + <value value="40" name="PERF_TP_L1_MISSES_ASTC_2TILE"/> + <value value="41" name="PERF_TP_L1_MISSES_ASTC_4TILE"/> + <value value="42" name="PERF_TP_L1_5_L2_COMPRESS_REQS"/> + <value value="43" name="PERF_TP_L1_5_L2_COMPRESS_MISS"/> + <value value="44" name="PERF_TP_L1_BANK_CONFLICT"/> + <value value="45" name="PERF_TP_L1_5_MISS_LATENCY_CYCLES"/> + <value value="46" name="PERF_TP_L1_5_MISS_LATENCY_TRANS"/> + <value value="47" name="PERF_TP_QUADS_CONSTANT_MULTIPLIED"/> + <value value="48" name="PERF_TP_FRONTEND_WORKING_CYCLES"/> + <value value="49" name="PERF_TP_L1_TAG_WORKING_CYCLES"/> + <value value="50" name="PERF_TP_L1_DATA_WRITE_WORKING_CYCLES"/> + <value value="51" name="PERF_TP_PRE_L1_DECOM_WORKING_CYCLES"/> + <value value="52" name="PERF_TP_BACKEND_WORKING_CYCLES"/> + <value value="53" name="PERF_TP_FLAG_CACHE_WORKING_CYCLES"/> + <value value="54" name="PERF_TP_L1_5_CACHE_WORKING_CYCLES"/> + <value value="55" name="PERF_TP_STARVE_CYCLES_SP"/> + <value value="56" name="PERF_TP_STARVE_CYCLES_UCHE"/> +</enum> + +<enum name="a6xx_sp_perfcounter_select"> + <value value="0" name="PERF_SP_BUSY_CYCLES"/> + <value value="1" name="PERF_SP_ALU_WORKING_CYCLES"/> + <value value="2" name="PERF_SP_EFU_WORKING_CYCLES"/> + <value value="3" name="PERF_SP_STALL_CYCLES_VPC"/> + <value value="4" name="PERF_SP_STALL_CYCLES_TP"/> + <value value="5" name="PERF_SP_STALL_CYCLES_UCHE"/> + <value value="6" name="PERF_SP_STALL_CYCLES_RB"/> + <value value="7" name="PERF_SP_NON_EXECUTION_CYCLES"/> + <value value="8" name="PERF_SP_WAVE_CONTEXTS"/> + <value value="9" name="PERF_SP_WAVE_CONTEXT_CYCLES"/> + <value value="10" name="PERF_SP_FS_STAGE_WAVE_CYCLES"/> + <value value="11" name="PERF_SP_FS_STAGE_WAVE_SAMPLES"/> + <value value="12" name="PERF_SP_VS_STAGE_WAVE_CYCLES"/> + <value value="13" name="PERF_SP_VS_STAGE_WAVE_SAMPLES"/> + <value value="14" name="PERF_SP_FS_STAGE_DURATION_CYCLES"/> + <value value="15" name="PERF_SP_VS_STAGE_DURATION_CYCLES"/> + <value value="16" name="PERF_SP_WAVE_CTRL_CYCLES"/> + <value value="17" name="PERF_SP_WAVE_LOAD_CYCLES"/> + <value value="18" name="PERF_SP_WAVE_EMIT_CYCLES"/> + <value value="19" name="PERF_SP_WAVE_NOP_CYCLES"/> + <value value="20" name="PERF_SP_WAVE_WAIT_CYCLES"/> + <value value="21" name="PERF_SP_WAVE_FETCH_CYCLES"/> + <value value="22" name="PERF_SP_WAVE_IDLE_CYCLES"/> + <value value="23" name="PERF_SP_WAVE_END_CYCLES"/> + <value value="24" name="PERF_SP_WAVE_LONG_SYNC_CYCLES"/> + <value value="25" name="PERF_SP_WAVE_SHORT_SYNC_CYCLES"/> + <value value="26" name="PERF_SP_WAVE_JOIN_CYCLES"/> + <value value="27" name="PERF_SP_LM_LOAD_INSTRUCTIONS"/> + <value value="28" name="PERF_SP_LM_STORE_INSTRUCTIONS"/> + <value value="29" name="PERF_SP_LM_ATOMICS"/> + <value value="30" name="PERF_SP_GM_LOAD_INSTRUCTIONS"/> + <value value="31" name="PERF_SP_GM_STORE_INSTRUCTIONS"/> + <value value="32" name="PERF_SP_GM_ATOMICS"/> + <value value="33" name="PERF_SP_VS_STAGE_TEX_INSTRUCTIONS"/> + <value value="34" name="PERF_SP_VS_STAGE_EFU_INSTRUCTIONS"/> + <value value="35" name="PERF_SP_VS_STAGE_FULL_ALU_INSTRUCTIONS"/> + <value value="36" name="PERF_SP_VS_STAGE_HALF_ALU_INSTRUCTIONS"/> + <value value="37" name="PERF_SP_FS_STAGE_TEX_INSTRUCTIONS"/> + <value value="38" name="PERF_SP_FS_STAGE_CFLOW_INSTRUCTIONS"/> + <value value="39" name="PERF_SP_FS_STAGE_EFU_INSTRUCTIONS"/> + <value value="40" name="PERF_SP_FS_STAGE_FULL_ALU_INSTRUCTIONS"/> + <value value="41" name="PERF_SP_FS_STAGE_HALF_ALU_INSTRUCTIONS"/> + <value value="42" name="PERF_SP_FS_STAGE_BARY_INSTRUCTIONS"/> + <value value="43" name="PERF_SP_VS_INSTRUCTIONS"/> + <value value="44" name="PERF_SP_FS_INSTRUCTIONS"/> + <value value="45" name="PERF_SP_ADDR_LOCK_COUNT"/> + <value value="46" name="PERF_SP_UCHE_READ_TRANS"/> + <value value="47" name="PERF_SP_UCHE_WRITE_TRANS"/> + <value value="48" name="PERF_SP_EXPORT_VPC_TRANS"/> + <value value="49" name="PERF_SP_EXPORT_RB_TRANS"/> + <value value="50" name="PERF_SP_PIXELS_KILLED"/> + <value value="51" name="PERF_SP_ICL1_REQUESTS"/> + <value value="52" name="PERF_SP_ICL1_MISSES"/> + <value value="53" name="PERF_SP_HS_INSTRUCTIONS"/> + <value value="54" name="PERF_SP_DS_INSTRUCTIONS"/> + <value value="55" name="PERF_SP_GS_INSTRUCTIONS"/> + <value value="56" name="PERF_SP_CS_INSTRUCTIONS"/> + <value value="57" name="PERF_SP_GPR_READ"/> + <value value="58" name="PERF_SP_GPR_WRITE"/> + <value value="59" name="PERF_SP_FS_STAGE_HALF_EFU_INSTRUCTIONS"/> + <value value="60" name="PERF_SP_VS_STAGE_HALF_EFU_INSTRUCTIONS"/> + <value value="61" name="PERF_SP_LM_BANK_CONFLICTS"/> + <value value="62" name="PERF_SP_TEX_CONTROL_WORKING_CYCLES"/> + <value value="63" name="PERF_SP_LOAD_CONTROL_WORKING_CYCLES"/> + <value value="64" name="PERF_SP_FLOW_CONTROL_WORKING_CYCLES"/> + <value value="65" name="PERF_SP_LM_WORKING_CYCLES"/> + <value value="66" name="PERF_SP_DISPATCHER_WORKING_CYCLES"/> + <value value="67" name="PERF_SP_SEQUENCER_WORKING_CYCLES"/> + <value value="68" name="PERF_SP_LOW_EFFICIENCY_STARVED_BY_TP"/> + <value value="69" name="PERF_SP_STARVE_CYCLES_HLSQ"/> + <value value="70" name="PERF_SP_NON_EXECUTION_LS_CYCLES"/> + <value value="71" name="PERF_SP_WORKING_EU"/> + <value value="72" name="PERF_SP_ANY_EU_WORKING"/> + <value value="73" name="PERF_SP_WORKING_EU_FS_STAGE"/> + <value value="74" name="PERF_SP_ANY_EU_WORKING_FS_STAGE"/> + <value value="75" name="PERF_SP_WORKING_EU_VS_STAGE"/> + <value value="76" name="PERF_SP_ANY_EU_WORKING_VS_STAGE"/> + <value value="77" name="PERF_SP_WORKING_EU_CS_STAGE"/> + <value value="78" name="PERF_SP_ANY_EU_WORKING_CS_STAGE"/> + <value value="79" name="PERF_SP_GPR_READ_PREFETCH"/> + <value value="80" name="PERF_SP_GPR_READ_CONFLICT"/> + <value value="81" name="PERF_SP_GPR_WRITE_CONFLICT"/> + <value value="82" name="PERF_SP_GM_LOAD_LATENCY_CYCLES"/> + <value value="83" name="PERF_SP_GM_LOAD_LATENCY_SAMPLES"/> + <value value="84" name="PERF_SP_EXECUTABLE_WAVES"/> +</enum> + +<enum name="a6xx_rb_perfcounter_select"> + <value value="0" name="PERF_RB_BUSY_CYCLES"/> + <value value="1" name="PERF_RB_STALL_CYCLES_HLSQ"/> + <value value="2" name="PERF_RB_STALL_CYCLES_FIFO0_FULL"/> + <value value="3" name="PERF_RB_STALL_CYCLES_FIFO1_FULL"/> + <value value="4" name="PERF_RB_STALL_CYCLES_FIFO2_FULL"/> + <value value="5" name="PERF_RB_STARVE_CYCLES_SP"/> + <value value="6" name="PERF_RB_STARVE_CYCLES_LRZ_TILE"/> + <value value="7" name="PERF_RB_STARVE_CYCLES_CCU"/> + <value value="8" name="PERF_RB_STARVE_CYCLES_Z_PLANE"/> + <value value="9" name="PERF_RB_STARVE_CYCLES_BARY_PLANE"/> + <value value="10" name="PERF_RB_Z_WORKLOAD"/> + <value value="11" name="PERF_RB_HLSQ_ACTIVE"/> + <value value="12" name="PERF_RB_Z_READ"/> + <value value="13" name="PERF_RB_Z_WRITE"/> + <value value="14" name="PERF_RB_C_READ"/> + <value value="15" name="PERF_RB_C_WRITE"/> + <value value="16" name="PERF_RB_TOTAL_PASS"/> + <value value="17" name="PERF_RB_Z_PASS"/> + <value value="18" name="PERF_RB_Z_FAIL"/> + <value value="19" name="PERF_RB_S_FAIL"/> + <value value="20" name="PERF_RB_BLENDED_FXP_COMPONENTS"/> + <value value="21" name="PERF_RB_BLENDED_FP16_COMPONENTS"/> + <value value="22" name="PERF_RB_PS_INVOCATIONS"/> + <value value="23" name="PERF_RB_2D_ALIVE_CYCLES"/> + <value value="24" name="PERF_RB_2D_STALL_CYCLES_A2D"/> + <value value="25" name="PERF_RB_2D_STARVE_CYCLES_SRC"/> + <value value="26" name="PERF_RB_2D_STARVE_CYCLES_SP"/> + <value value="27" name="PERF_RB_2D_STARVE_CYCLES_DST"/> + <value value="28" name="PERF_RB_2D_VALID_PIXELS"/> + <value value="29" name="PERF_RB_3D_PIXELS"/> + <value value="30" name="PERF_RB_BLENDER_WORKING_CYCLES"/> + <value value="31" name="PERF_RB_ZPROC_WORKING_CYCLES"/> + <value value="32" name="PERF_RB_CPROC_WORKING_CYCLES"/> + <value value="33" name="PERF_RB_SAMPLER_WORKING_CYCLES"/> + <value value="34" name="PERF_RB_STALL_CYCLES_CCU_COLOR_READ"/> + <value value="35" name="PERF_RB_STALL_CYCLES_CCU_COLOR_WRITE"/> + <value value="36" name="PERF_RB_STALL_CYCLES_CCU_DEPTH_READ"/> + <value value="37" name="PERF_RB_STALL_CYCLES_CCU_DEPTH_WRITE"/> + <value value="38" name="PERF_RB_STALL_CYCLES_VPC"/> + <value value="39" name="PERF_RB_2D_INPUT_TRANS"/> + <value value="40" name="PERF_RB_2D_OUTPUT_RB_DST_TRANS"/> + <value value="41" name="PERF_RB_2D_OUTPUT_RB_SRC_TRANS"/> + <value value="42" name="PERF_RB_BLENDED_FP32_COMPONENTS"/> + <value value="43" name="PERF_RB_COLOR_PIX_TILES"/> + <value value="44" name="PERF_RB_STALL_CYCLES_CCU"/> + <value value="45" name="PERF_RB_EARLY_Z_ARB3_GRANT"/> + <value value="46" name="PERF_RB_LATE_Z_ARB3_GRANT"/> + <value value="47" name="PERF_RB_EARLY_Z_SKIP_GRANT"/> +</enum> + +<enum name="a6xx_vsc_perfcounter_select"> + <value value="0" name="PERF_VSC_BUSY_CYCLES"/> + <value value="1" name="PERF_VSC_WORKING_CYCLES"/> + <value value="2" name="PERF_VSC_STALL_CYCLES_UCHE"/> + <value value="3" name="PERF_VSC_EOT_NUM"/> + <value value="4" name="PERF_VSC_INPUT_TILES"/> +</enum> + +<enum name="a6xx_ccu_perfcounter_select"> + <value value="0" name="PERF_CCU_BUSY_CYCLES"/> + <value value="1" name="PERF_CCU_STALL_CYCLES_RB_DEPTH_RETURN"/> + <value value="2" name="PERF_CCU_STALL_CYCLES_RB_COLOR_RETURN"/> + <value value="3" name="PERF_CCU_STARVE_CYCLES_FLAG_RETURN"/> + <value value="4" name="PERF_CCU_DEPTH_BLOCKS"/> + <value value="5" name="PERF_CCU_COLOR_BLOCKS"/> + <value value="6" name="PERF_CCU_DEPTH_BLOCK_HIT"/> + <value value="7" name="PERF_CCU_COLOR_BLOCK_HIT"/> + <value value="8" name="PERF_CCU_PARTIAL_BLOCK_READ"/> + <value value="9" name="PERF_CCU_GMEM_READ"/> + <value value="10" name="PERF_CCU_GMEM_WRITE"/> + <value value="11" name="PERF_CCU_DEPTH_READ_FLAG0_COUNT"/> + <value value="12" name="PERF_CCU_DEPTH_READ_FLAG1_COUNT"/> + <value value="13" name="PERF_CCU_DEPTH_READ_FLAG2_COUNT"/> + <value value="14" name="PERF_CCU_DEPTH_READ_FLAG3_COUNT"/> + <value value="15" name="PERF_CCU_DEPTH_READ_FLAG4_COUNT"/> + <value value="16" name="PERF_CCU_DEPTH_READ_FLAG5_COUNT"/> + <value value="17" name="PERF_CCU_DEPTH_READ_FLAG6_COUNT"/> + <value value="18" name="PERF_CCU_DEPTH_READ_FLAG8_COUNT"/> + <value value="19" name="PERF_CCU_COLOR_READ_FLAG0_COUNT"/> + <value value="20" name="PERF_CCU_COLOR_READ_FLAG1_COUNT"/> + <value value="21" name="PERF_CCU_COLOR_READ_FLAG2_COUNT"/> + <value value="22" name="PERF_CCU_COLOR_READ_FLAG3_COUNT"/> + <value value="23" name="PERF_CCU_COLOR_READ_FLAG4_COUNT"/> + <value value="24" name="PERF_CCU_COLOR_READ_FLAG5_COUNT"/> + <value value="25" name="PERF_CCU_COLOR_READ_FLAG6_COUNT"/> + <value value="26" name="PERF_CCU_COLOR_READ_FLAG8_COUNT"/> + <value value="27" name="PERF_CCU_2D_RD_REQ"/> + <value value="28" name="PERF_CCU_2D_WR_REQ"/> +</enum> + +<enum name="a6xx_lrz_perfcounter_select"> + <value value="0" name="PERF_LRZ_BUSY_CYCLES"/> + <value value="1" name="PERF_LRZ_STARVE_CYCLES_RAS"/> + <value value="2" name="PERF_LRZ_STALL_CYCLES_RB"/> + <value value="3" name="PERF_LRZ_STALL_CYCLES_VSC"/> + <value value="4" name="PERF_LRZ_STALL_CYCLES_VPC"/> + <value value="5" name="PERF_LRZ_STALL_CYCLES_FLAG_PREFETCH"/> + <value value="6" name="PERF_LRZ_STALL_CYCLES_UCHE"/> + <value value="7" name="PERF_LRZ_LRZ_READ"/> + <value value="8" name="PERF_LRZ_LRZ_WRITE"/> + <value value="9" name="PERF_LRZ_READ_LATENCY"/> + <value value="10" name="PERF_LRZ_MERGE_CACHE_UPDATING"/> + <value value="11" name="PERF_LRZ_PRIM_KILLED_BY_MASKGEN"/> + <value value="12" name="PERF_LRZ_PRIM_KILLED_BY_LRZ"/> + <value value="13" name="PERF_LRZ_VISIBLE_PRIM_AFTER_LRZ"/> + <value value="14" name="PERF_LRZ_FULL_8X8_TILES"/> + <value value="15" name="PERF_LRZ_PARTIAL_8X8_TILES"/> + <value value="16" name="PERF_LRZ_TILE_KILLED"/> + <value value="17" name="PERF_LRZ_TOTAL_PIXEL"/> + <value value="18" name="PERF_LRZ_VISIBLE_PIXEL_AFTER_LRZ"/> + <value value="19" name="PERF_LRZ_FULLY_COVERED_TILES"/> + <value value="20" name="PERF_LRZ_PARTIAL_COVERED_TILES"/> + <value value="21" name="PERF_LRZ_FEEDBACK_ACCEPT"/> + <value value="22" name="PERF_LRZ_FEEDBACK_DISCARD"/> + <value value="23" name="PERF_LRZ_FEEDBACK_STALL"/> + <value value="24" name="PERF_LRZ_STALL_CYCLES_RB_ZPLANE"/> + <value value="25" name="PERF_LRZ_STALL_CYCLES_RB_BPLANE"/> + <value value="26" name="PERF_LRZ_STALL_CYCLES_VC"/> + <value value="27" name="PERF_LRZ_RAS_MASK_TRANS"/> +</enum> + +<enum name="a6xx_cmp_perfcounter_select"> + <value value="0" name="PERF_CMPDECMP_STALL_CYCLES_ARB"/> + <value value="1" name="PERF_CMPDECMP_VBIF_LATENCY_CYCLES"/> + <value value="2" name="PERF_CMPDECMP_VBIF_LATENCY_SAMPLES"/> + <value value="3" name="PERF_CMPDECMP_VBIF_READ_DATA_CCU"/> + <value value="4" name="PERF_CMPDECMP_VBIF_WRITE_DATA_CCU"/> + <value value="5" name="PERF_CMPDECMP_VBIF_READ_REQUEST"/> + <value value="6" name="PERF_CMPDECMP_VBIF_WRITE_REQUEST"/> + <value value="7" name="PERF_CMPDECMP_VBIF_READ_DATA"/> + <value value="8" name="PERF_CMPDECMP_VBIF_WRITE_DATA"/> + <value value="9" name="PERF_CMPDECMP_FLAG_FETCH_CYCLES"/> + <value value="10" name="PERF_CMPDECMP_FLAG_FETCH_SAMPLES"/> + <value value="11" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG1_COUNT"/> + <value value="12" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG2_COUNT"/> + <value value="13" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG3_COUNT"/> + <value value="14" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG4_COUNT"/> + <value value="15" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG5_COUNT"/> + <value value="16" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG6_COUNT"/> + <value value="17" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG8_COUNT"/> + <value value="18" name="PERF_CMPDECMP_COLOR_WRITE_FLAG1_COUNT"/> + <value value="19" name="PERF_CMPDECMP_COLOR_WRITE_FLAG2_COUNT"/> + <value value="20" name="PERF_CMPDECMP_COLOR_WRITE_FLAG3_COUNT"/> + <value value="21" name="PERF_CMPDECMP_COLOR_WRITE_FLAG4_COUNT"/> + <value value="22" name="PERF_CMPDECMP_COLOR_WRITE_FLAG5_COUNT"/> + <value value="23" name="PERF_CMPDECMP_COLOR_WRITE_FLAG6_COUNT"/> + <value value="24" name="PERF_CMPDECMP_COLOR_WRITE_FLAG8_COUNT"/> + <value value="25" name="PERF_CMPDECMP_2D_STALL_CYCLES_VBIF_REQ"/> + <value value="26" name="PERF_CMPDECMP_2D_STALL_CYCLES_VBIF_WR"/> + <value value="27" name="PERF_CMPDECMP_2D_STALL_CYCLES_VBIF_RETURN"/> + <value value="28" name="PERF_CMPDECMP_2D_RD_DATA"/> + <value value="29" name="PERF_CMPDECMP_2D_WR_DATA"/> + <value value="30" name="PERF_CMPDECMP_VBIF_READ_DATA_UCHE_CH0"/> + <value value="31" name="PERF_CMPDECMP_VBIF_READ_DATA_UCHE_CH1"/> + <value value="32" name="PERF_CMPDECMP_2D_OUTPUT_TRANS"/> + <value value="33" name="PERF_CMPDECMP_VBIF_WRITE_DATA_UCHE"/> + <value value="34" name="PERF_CMPDECMP_DEPTH_WRITE_FLAG0_COUNT"/> + <value value="35" name="PERF_CMPDECMP_COLOR_WRITE_FLAG0_COUNT"/> + <value value="36" name="PERF_CMPDECMP_COLOR_WRITE_FLAGALPHA_COUNT"/> + <value value="37" name="PERF_CMPDECMP_2D_BUSY_CYCLES"/> + <value value="38" name="PERF_CMPDECMP_2D_REORDER_STARVE_CYCLES"/> + <value value="39" name="PERF_CMPDECMP_2D_PIXELS"/> +</enum> + +</database> diff --git a/drivers/gpu/drm/msm/registers/adreno/a7xx_enums.xml b/drivers/gpu/drm/msm/registers/adreno/a7xx_enums.xml new file mode 100644 index 000000000000..8d195ee5d284 --- /dev/null +++ b/drivers/gpu/drm/msm/registers/adreno/a7xx_enums.xml @@ -0,0 +1,216 @@ +<?xml version="1.0" encoding="UTF-8"?> +<database xmlns="http://nouveau.freedesktop.org/" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> +<import file="freedreno_copyright.xml"/> +<import file="adreno/adreno_common.xml"/> +<import file="adreno/adreno_pm4.xml"/> + +<enum name="a7xx_statetype_id"> + <value value="0" name="A7XX_TP0_NCTX_REG"/> + <value value="1" name="A7XX_TP0_CTX0_3D_CVS_REG"/> + <value value="2" name="A7XX_TP0_CTX0_3D_CPS_REG"/> + <value value="3" name="A7XX_TP0_CTX1_3D_CVS_REG"/> + <value value="4" name="A7XX_TP0_CTX1_3D_CPS_REG"/> + <value value="5" name="A7XX_TP0_CTX2_3D_CPS_REG"/> + <value value="6" name="A7XX_TP0_CTX3_3D_CPS_REG"/> + <value value="9" name="A7XX_TP0_TMO_DATA"/> + <value value="10" name="A7XX_TP0_SMO_DATA"/> + <value value="11" name="A7XX_TP0_MIPMAP_BASE_DATA"/> + <value value="32" name="A7XX_SP_NCTX_REG"/> + <value value="33" name="A7XX_SP_CTX0_3D_CVS_REG"/> + <value value="34" name="A7XX_SP_CTX0_3D_CPS_REG"/> + <value value="35" name="A7XX_SP_CTX1_3D_CVS_REG"/> + <value value="36" name="A7XX_SP_CTX1_3D_CPS_REG"/> + <value value="37" name="A7XX_SP_CTX2_3D_CPS_REG"/> + <value value="38" name="A7XX_SP_CTX3_3D_CPS_REG"/> + <value value="39" name="A7XX_SP_INST_DATA"/> + <value value="40" name="A7XX_SP_INST_DATA_1"/> + <value value="41" name="A7XX_SP_LB_0_DATA"/> + <value value="42" name="A7XX_SP_LB_1_DATA"/> + <value value="43" name="A7XX_SP_LB_2_DATA"/> + <value value="44" name="A7XX_SP_LB_3_DATA"/> + <value value="45" name="A7XX_SP_LB_4_DATA"/> + <value value="46" name="A7XX_SP_LB_5_DATA"/> + <value value="47" name="A7XX_SP_LB_6_DATA"/> + <value value="48" name="A7XX_SP_LB_7_DATA"/> + <value value="49" name="A7XX_SP_CB_RAM"/> + <value value="50" name="A7XX_SP_LB_13_DATA"/> + <value value="51" name="A7XX_SP_LB_14_DATA"/> + <value value="52" name="A7XX_SP_INST_TAG"/> + <value value="53" name="A7XX_SP_INST_DATA_2"/> + <value value="54" name="A7XX_SP_TMO_TAG"/> + <value value="55" name="A7XX_SP_SMO_TAG"/> + <value value="56" name="A7XX_SP_STATE_DATA"/> + <value value="57" name="A7XX_SP_HWAVE_RAM"/> + <value value="58" name="A7XX_SP_L0_INST_BUF"/> + <value value="59" name="A7XX_SP_LB_8_DATA"/> + <value value="60" name="A7XX_SP_LB_9_DATA"/> + <value value="61" name="A7XX_SP_LB_10_DATA"/> + <value value="62" name="A7XX_SP_LB_11_DATA"/> + <value value="63" name="A7XX_SP_LB_12_DATA"/> + <value value="64" name="A7XX_HLSQ_DATAPATH_DSTR_META"/> + <value value="67" name="A7XX_HLSQ_L2STC_TAG_RAM"/> + <value value="68" name="A7XX_HLSQ_L2STC_INFO_CMD"/> + <value value="69" name="A7XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG"/> + <value value="70" name="A7XX_HLSQ_CPS_BE_CTXT_BUF_RAM_TAG"/> + <value value="71" name="A7XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM"/> + <value value="72" name="A7XX_HLSQ_GFX_CPS_BE_CTXT_BUF_RAM"/> + <value value="73" name="A7XX_HLSQ_CHUNK_CVS_RAM"/> + <value value="74" name="A7XX_HLSQ_CHUNK_CPS_RAM"/> + <value value="75" name="A7XX_HLSQ_CHUNK_CVS_RAM_TAG"/> + <value value="76" name="A7XX_HLSQ_CHUNK_CPS_RAM_TAG"/> + <value value="77" name="A7XX_HLSQ_ICB_CVS_CB_BASE_TAG"/> + <value value="78" name="A7XX_HLSQ_ICB_CPS_CB_BASE_TAG"/> + <value value="79" name="A7XX_HLSQ_CVS_MISC_RAM"/> + <value value="80" name="A7XX_HLSQ_CPS_MISC_RAM"/> + <value value="81" name="A7XX_HLSQ_CPS_MISC_RAM_1"/> + <value value="82" name="A7XX_HLSQ_INST_RAM"/> + <value value="83" name="A7XX_HLSQ_GFX_CVS_CONST_RAM"/> + <value value="84" name="A7XX_HLSQ_GFX_CPS_CONST_RAM"/> + <value value="85" name="A7XX_HLSQ_CVS_MISC_RAM_TAG"/> + <value value="86" name="A7XX_HLSQ_CPS_MISC_RAM_TAG"/> + <value value="87" name="A7XX_HLSQ_INST_RAM_TAG"/> + <value value="88" name="A7XX_HLSQ_GFX_CVS_CONST_RAM_TAG"/> + <value value="89" name="A7XX_HLSQ_GFX_CPS_CONST_RAM_TAG"/> + <value value="90" name="A7XX_HLSQ_GFX_LOCAL_MISC_RAM"/> + <value value="91" name="A7XX_HLSQ_GFX_LOCAL_MISC_RAM_TAG"/> + <value value="92" name="A7XX_HLSQ_INST_RAM_1"/> + <value value="93" name="A7XX_HLSQ_STPROC_META"/> + <value value="94" name="A7XX_HLSQ_BV_BE_META"/> + <value value="95" name="A7XX_HLSQ_INST_RAM_2"/> + <value value="96" name="A7XX_HLSQ_DATAPATH_META"/> + <value value="97" name="A7XX_HLSQ_FRONTEND_META"/> + <value value="98" name="A7XX_HLSQ_INDIRECT_META"/> + <value value="99" name="A7XX_HLSQ_BACKEND_META"/> +</enum> + +<enum name="a7xx_state_location"> + <value value="0" name="A7XX_HLSQ_STATE"/> + <value value="1" name="A7XX_HLSQ_DP"/> + <value value="2" name="A7XX_SP_TOP"/> + <value value="3" name="A7XX_USPTP"/> + <value value="4" name="A7XX_HLSQ_DP_STR"/> +</enum> + +<enum name="a7xx_cluster"> + <value value="0" name="A7XX_CLUSTER_NONE"/> + <value value="1" name="A7XX_CLUSTER_FE"/> + <value value="2" name="A7XX_CLUSTER_SP_VS"/> + <value value="3" name="A7XX_CLUSTER_PC_VS"/> + <value value="4" name="A7XX_CLUSTER_GRAS"/> + <value value="5" name="A7XX_CLUSTER_SP_PS"/> + <value value="6" name="A7XX_CLUSTER_VPC_PS"/> + <value value="7" name="A7XX_CLUSTER_PS"/> +</enum> + +<enum name="a7xx_debugbus_id"> + <value value="1" name="A7XX_DBGBUS_CP_0_0"/> + <value value="2" name="A7XX_DBGBUS_CP_0_1"/> + <value value="3" name="A7XX_DBGBUS_RBBM"/> + <value value="5" name="A7XX_DBGBUS_GBIF_GX"/> + <value value="6" name="A7XX_DBGBUS_GBIF_CX"/> + <value value="7" name="A7XX_DBGBUS_HLSQ"/> + <value value="9" name="A7XX_DBGBUS_UCHE_0"/> + <value value="10" name="A7XX_DBGBUS_UCHE_1"/> + <value value="13" name="A7XX_DBGBUS_TESS_BR"/> + <value value="14" name="A7XX_DBGBUS_TESS_BV"/> + <value value="17" name="A7XX_DBGBUS_PC_BR"/> + <value value="18" name="A7XX_DBGBUS_PC_BV"/> + <value value="21" name="A7XX_DBGBUS_VFDP_BR"/> + <value value="22" name="A7XX_DBGBUS_VFDP_BV"/> + <value value="25" name="A7XX_DBGBUS_VPC_BR"/> + <value value="26" name="A7XX_DBGBUS_VPC_BV"/> + <value value="29" name="A7XX_DBGBUS_TSE_BR"/> + <value value="30" name="A7XX_DBGBUS_TSE_BV"/> + <value value="33" name="A7XX_DBGBUS_RAS_BR"/> + <value value="34" name="A7XX_DBGBUS_RAS_BV"/> + <value value="37" name="A7XX_DBGBUS_VSC"/> + <value value="39" name="A7XX_DBGBUS_COM_0"/> + <value value="43" name="A7XX_DBGBUS_LRZ_BR"/> + <value value="44" name="A7XX_DBGBUS_LRZ_BV"/> + <value value="47" name="A7XX_DBGBUS_UFC_0"/> + <value value="48" name="A7XX_DBGBUS_UFC_1"/> + <value value="55" name="A7XX_DBGBUS_GMU_GX"/> + <value value="59" name="A7XX_DBGBUS_DBGC"/> + <value value="60" name="A7XX_DBGBUS_CX"/> + <value value="61" name="A7XX_DBGBUS_GMU_CX"/> + <value value="62" name="A7XX_DBGBUS_GPC_BR"/> + <value value="63" name="A7XX_DBGBUS_GPC_BV"/> + <value value="66" name="A7XX_DBGBUS_LARC"/> + <value value="68" name="A7XX_DBGBUS_HLSQ_SPTP"/> + <value value="70" name="A7XX_DBGBUS_RB_0"/> + <value value="71" name="A7XX_DBGBUS_RB_1"/> + <value value="72" name="A7XX_DBGBUS_RB_2"/> + <value value="73" name="A7XX_DBGBUS_RB_3"/> + <value value="74" name="A7XX_DBGBUS_RB_4"/> + <value value="75" name="A7XX_DBGBUS_RB_5"/> + <value value="102" name="A7XX_DBGBUS_UCHE_WRAPPER"/> + <value value="106" name="A7XX_DBGBUS_CCU_0"/> + <value value="107" name="A7XX_DBGBUS_CCU_1"/> + <value value="108" name="A7XX_DBGBUS_CCU_2"/> + <value value="109" name="A7XX_DBGBUS_CCU_3"/> + <value value="110" name="A7XX_DBGBUS_CCU_4"/> + <value value="111" name="A7XX_DBGBUS_CCU_5"/> + <value value="138" name="A7XX_DBGBUS_VFD_BR_0"/> + <value value="139" name="A7XX_DBGBUS_VFD_BR_1"/> + <value value="140" name="A7XX_DBGBUS_VFD_BR_2"/> + <value value="141" name="A7XX_DBGBUS_VFD_BR_3"/> + <value value="142" name="A7XX_DBGBUS_VFD_BR_4"/> + <value value="143" name="A7XX_DBGBUS_VFD_BR_5"/> + <value value="144" name="A7XX_DBGBUS_VFD_BR_6"/> + <value value="145" name="A7XX_DBGBUS_VFD_BR_7"/> + <value value="202" name="A7XX_DBGBUS_VFD_BV_0"/> + <value value="203" name="A7XX_DBGBUS_VFD_BV_1"/> + <value value="204" name="A7XX_DBGBUS_VFD_BV_2"/> + <value value="205" name="A7XX_DBGBUS_VFD_BV_3"/> + <value value="234" name="A7XX_DBGBUS_USP_0"/> + <value value="235" name="A7XX_DBGBUS_USP_1"/> + <value value="236" name="A7XX_DBGBUS_USP_2"/> + <value value="237" name="A7XX_DBGBUS_USP_3"/> + <value value="238" name="A7XX_DBGBUS_USP_4"/> + <value value="239" name="A7XX_DBGBUS_USP_5"/> + <value value="266" name="A7XX_DBGBUS_TP_0"/> + <value value="267" name="A7XX_DBGBUS_TP_1"/> + <value value="268" name="A7XX_DBGBUS_TP_2"/> + <value value="269" name="A7XX_DBGBUS_TP_3"/> + <value value="270" name="A7XX_DBGBUS_TP_4"/> + <value value="271" name="A7XX_DBGBUS_TP_5"/> + <value value="272" name="A7XX_DBGBUS_TP_6"/> + <value value="273" name="A7XX_DBGBUS_TP_7"/> + <value value="274" name="A7XX_DBGBUS_TP_8"/> + <value value="275" name="A7XX_DBGBUS_TP_9"/> + <value value="276" name="A7XX_DBGBUS_TP_10"/> + <value value="277" name="A7XX_DBGBUS_TP_11"/> + <value value="330" name="A7XX_DBGBUS_USPTP_0"/> + <value value="331" name="A7XX_DBGBUS_USPTP_1"/> + <value value="332" name="A7XX_DBGBUS_USPTP_2"/> + <value value="333" name="A7XX_DBGBUS_USPTP_3"/> + <value value="334" name="A7XX_DBGBUS_USPTP_4"/> + <value value="335" name="A7XX_DBGBUS_USPTP_5"/> + <value value="336" name="A7XX_DBGBUS_USPTP_6"/> + <value value="337" name="A7XX_DBGBUS_USPTP_7"/> + <value value="338" name="A7XX_DBGBUS_USPTP_8"/> + <value value="339" name="A7XX_DBGBUS_USPTP_9"/> + <value value="340" name="A7XX_DBGBUS_USPTP_10"/> + <value value="341" name="A7XX_DBGBUS_USPTP_11"/> + <value value="396" name="A7XX_DBGBUS_CCHE_0"/> + <value value="397" name="A7XX_DBGBUS_CCHE_1"/> + <value value="398" name="A7XX_DBGBUS_CCHE_2"/> + <value value="408" name="A7XX_DBGBUS_VPC_DSTR_0"/> + <value value="409" name="A7XX_DBGBUS_VPC_DSTR_1"/> + <value value="410" name="A7XX_DBGBUS_VPC_DSTR_2"/> + <value value="411" name="A7XX_DBGBUS_HLSQ_DP_STR_0"/> + <value value="412" name="A7XX_DBGBUS_HLSQ_DP_STR_1"/> + <value value="413" name="A7XX_DBGBUS_HLSQ_DP_STR_2"/> + <value value="414" name="A7XX_DBGBUS_HLSQ_DP_STR_3"/> + <value value="415" name="A7XX_DBGBUS_HLSQ_DP_STR_4"/> + <value value="416" name="A7XX_DBGBUS_HLSQ_DP_STR_5"/> + <value value="443" name="A7XX_DBGBUS_UFC_DSTR_0"/> + <value value="444" name="A7XX_DBGBUS_UFC_DSTR_1"/> + <value value="445" name="A7XX_DBGBUS_UFC_DSTR_2"/> + <value value="446" name="A7XX_DBGBUS_CGC_SUBCORE"/> + <value value="447" name="A7XX_DBGBUS_CGC_CORE"/> +</enum> + +</database> diff --git a/drivers/gpu/drm/msm/registers/adreno/a7xx_perfcntrs.xml b/drivers/gpu/drm/msm/registers/adreno/a7xx_perfcntrs.xml new file mode 100644 index 000000000000..9bf78b0a854b --- /dev/null +++ b/drivers/gpu/drm/msm/registers/adreno/a7xx_perfcntrs.xml @@ -0,0 +1,1030 @@ +<?xml version="1.0" encoding="UTF-8"?> +<database xmlns="http://nouveau.freedesktop.org/" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> +<import file="freedreno_copyright.xml"/> +<import file="adreno/adreno_common.xml"/> +<import file="adreno/adreno_pm4.xml"/> + +<enum name="a7xx_cp_perfcounter_select"> + <value value="0" name="A7XX_PERF_CP_ALWAYS_COUNT"/> + <value value="1" name="A7XX_PERF_CP_BUSY_GFX_CORE_IDLE"/> + <value value="2" name="A7XX_PERF_CP_BUSY_CYCLES"/> + <value value="3" name="A7XX_PERF_CP_NUM_PREEMPTIONS"/> + <value value="4" name="A7XX_PERF_CP_PREEMPTION_REACTION_DELAY"/> + <value value="5" name="A7XX_PERF_CP_PREEMPTION_SWITCH_OUT_TIME"/> + <value value="6" name="A7XX_PERF_CP_PREEMPTION_SWITCH_IN_TIME"/> + <value value="7" name="A7XX_PERF_CP_DEAD_DRAWS_IN_BIN_RENDER"/> + <value value="8" name="A7XX_PERF_CP_PREDICATED_DRAWS_KILLED"/> + <value value="9" name="A7XX_PERF_CP_MODE_SWITCH"/> + <value value="10" name="A7XX_PERF_CP_ZPASS_DONE"/> + <value value="11" name="A7XX_PERF_CP_CONTEXT_DONE"/> + <value value="12" name="A7XX_PERF_CP_CACHE_FLUSH"/> + <value value="13" name="A7XX_PERF_CP_LONG_PREEMPTIONS"/> + <value value="14" name="A7XX_PERF_CP_SQE_I_CACHE_STARVE"/> + <value value="15" name="A7XX_PERF_CP_SQE_IDLE"/> + <value value="16" name="A7XX_PERF_CP_SQE_PM4_STARVE_RB_IB"/> + <value value="17" name="A7XX_PERF_CP_SQE_PM4_STARVE_SDS"/> + <value value="18" name="A7XX_PERF_CP_SQE_MRB_STARVE"/> + <value value="19" name="A7XX_PERF_CP_SQE_RRB_STARVE"/> + <value value="20" name="A7XX_PERF_CP_SQE_VSD_STARVE"/> + <value value="21" name="A7XX_PERF_CP_VSD_DECODE_STARVE"/> + <value value="22" name="A7XX_PERF_CP_SQE_PIPE_OUT_STALL"/> + <value value="23" name="A7XX_PERF_CP_SQE_SYNC_STALL"/> + <value value="24" name="A7XX_PERF_CP_SQE_PM4_WFI_STALL"/> + <value value="25" name="A7XX_PERF_CP_SQE_SYS_WFI_STALL"/> + <value value="26" name="A7XX_PERF_CP_SQE_T4_EXEC"/> + <value value="27" name="A7XX_PERF_CP_SQE_LOAD_STATE_EXEC"/> + <value value="28" name="A7XX_PERF_CP_SQE_SAVE_SDS_STATE"/> + <value value="29" name="A7XX_PERF_CP_SQE_DRAW_EXEC"/> + <value value="30" name="A7XX_PERF_CP_SQE_CTXT_REG_BUNCH_EXEC"/> + <value value="31" name="A7XX_PERF_CP_SQE_EXEC_PROFILED"/> + <value value="32" name="A7XX_PERF_CP_MEMORY_POOL_EMPTY"/> + <value value="33" name="A7XX_PERF_CP_MEMORY_POOL_SYNC_STALL"/> + <value value="34" name="A7XX_PERF_CP_MEMORY_POOL_ABOVE_THRESH"/> + <value value="35" name="A7XX_PERF_CP_AHB_WR_STALL_PRE_DRAWS"/> + <value value="36" name="A7XX_PERF_CP_AHB_STALL_SQE_GMU"/> + <value value="37" name="A7XX_PERF_CP_AHB_STALL_SQE_WR_OTHER"/> + <value value="38" name="A7XX_PERF_CP_AHB_STALL_SQE_RD_OTHER"/> + <value value="39" name="A7XX_PERF_CP_CLUSTER0_EMPTY"/> + <value value="40" name="A7XX_PERF_CP_CLUSTER1_EMPTY"/> + <value value="41" name="A7XX_PERF_CP_CLUSTER2_EMPTY"/> + <value value="42" name="A7XX_PERF_CP_CLUSTER3_EMPTY"/> + <value value="43" name="A7XX_PERF_CP_CLUSTER4_EMPTY"/> + <value value="44" name="A7XX_PERF_CP_CLUSTER5_EMPTY"/> + <value value="45" name="A7XX_PERF_CP_PM4_DATA"/> + <value value="46" name="A7XX_PERF_CP_PM4_HEADERS"/> + <value value="47" name="A7XX_PERF_CP_VBIF_READ_BEATS"/> + <value value="48" name="A7XX_PERF_CP_VBIF_WRITE_BEATS"/> + <value value="49" name="A7XX_PERF_CP_SQE_INSTR_COUNTER"/> + <value value="50" name="A7XX_PERF_CP_RESERVED_50"/> + <value value="51" name="A7XX_PERF_CP_RESERVED_51"/> + <value value="52" name="A7XX_PERF_CP_RESERVED_52"/> + <value value="53" name="A7XX_PERF_CP_RESERVED_53"/> + <value value="54" name="A7XX_PERF_CP_RESERVED_54"/> + <value value="55" name="A7XX_PERF_CP_RESERVED_55"/> + <value value="56" name="A7XX_PERF_CP_RESERVED_56"/> + <value value="57" name="A7XX_PERF_CP_RESERVED_57"/> + <value value="58" name="A7XX_PERF_CP_RESERVED_58"/> + <value value="59" name="A7XX_PERF_CP_RESERVED_59"/> + <value value="60" name="A7XX_PERF_CP_CLUSTER0_FULL"/> + <value value="61" name="A7XX_PERF_CP_CLUSTER1_FULL"/> + <value value="62" name="A7XX_PERF_CP_CLUSTER2_FULL"/> + <value value="63" name="A7XX_PERF_CP_CLUSTER3_FULL"/> + <value value="64" name="A7XX_PERF_CP_CLUSTER4_FULL"/> + <value value="65" name="A7XX_PERF_CP_CLUSTER5_FULL"/> + <value value="66" name="A7XX_PERF_CP_CLUSTER6_FULL"/> + <value value="67" name="A7XX_PERF_CP_CLUSTER6_EMPTY"/> + <value value="68" name="A7XX_PERF_CP_ICACHE_MISSES"/> + <value value="69" name="A7XX_PERF_CP_ICACHE_HITS"/> + <value value="70" name="A7XX_PERF_CP_ICACHE_STALL"/> + <value value="71" name="A7XX_PERF_CP_DCACHE_MISSES"/> + <value value="72" name="A7XX_PERF_CP_DCACHE_HITS"/> + <value value="73" name="A7XX_PERF_CP_DCACHE_STALLS"/> + <value value="74" name="A7XX_PERF_CP_AQE_SQE_STALL"/> + <value value="75" name="A7XX_PERF_CP_SQE_AQE_STARVE"/> + <value value="76" name="A7XX_PERF_CP_PREEMPT_LATENCY"/> + <value value="77" name="A7XX_PERF_CP_SQE_MD8_STALL_CYCLES"/> + <value value="78" name="A7XX_PERF_CP_SQE_MESH_EXEC_CYCLES"/> + <value value="79" name="A7XX_PERF_CP_AQE_NUM_AS_CHUNKS"/> + <value value="80" name="A7XX_PERF_CP_AQE_NUM_MS_CHUNKS"/> +</enum> + +<enum name="a7xx_rbbm_perfcounter_select"> + <value value="0" name="A7XX_PERF_RBBM_ALWAYS_COUNT"/> + <value value="1" name="A7XX_PERF_RBBM_ALWAYS_ON"/> + <value value="2" name="A7XX_PERF_RBBM_TSE_BUSY"/> + <value value="3" name="A7XX_PERF_RBBM_RAS_BUSY"/> + <value value="4" name="A7XX_PERF_RBBM_PC_DCALL_BUSY"/> + <value value="5" name="A7XX_PERF_RBBM_PC_VSD_BUSY"/> + <value value="6" name="A7XX_PERF_RBBM_STATUS_MASKED"/> + <value value="7" name="A7XX_PERF_RBBM_COM_BUSY"/> + <value value="8" name="A7XX_PERF_RBBM_DCOM_BUSY"/> + <value value="9" name="A7XX_PERF_RBBM_VBIF_BUSY"/> + <value value="10" name="A7XX_PERF_RBBM_VSC_BUSY"/> + <value value="11" name="A7XX_PERF_RBBM_TESS_BUSY"/> + <value value="12" name="A7XX_PERF_RBBM_UCHE_BUSY"/> + <value value="13" name="A7XX_PERF_RBBM_HLSQ_BUSY"/> +</enum> + +<enum name="a7xx_pc_perfcounter_select"> + <value value="0" name="A7XX_PERF_PC_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_PC_WORKING_CYCLES"/> + <value value="2" name="A7XX_PERF_PC_STALL_CYCLES_VFD"/> + <value value="3" name="A7XX_PERF_PC_RESERVED"/> + <value value="4" name="A7XX_PERF_PC_STALL_CYCLES_VPC"/> + <value value="5" name="A7XX_PERF_PC_STALL_CYCLES_UCHE"/> + <value value="6" name="A7XX_PERF_PC_STALL_CYCLES_TESS"/> + <value value="7" name="A7XX_PERF_PC_STALL_CYCLES_VFD_ONLY"/> + <value value="8" name="A7XX_PERF_PC_STALL_CYCLES_VPC_ONLY"/> + <value value="9" name="A7XX_PERF_PC_PASS1_TF_STALL_CYCLES"/> + <value value="10" name="A7XX_PERF_PC_STARVE_CYCLES_FOR_INDEX"/> + <value value="11" name="A7XX_PERF_PC_STARVE_CYCLES_FOR_TESS_FACTOR"/> + <value value="12" name="A7XX_PERF_PC_STARVE_CYCLES_FOR_VIZ_STREAM"/> + <value value="13" name="A7XX_PERF_PC_STARVE_CYCLES_DI"/> + <value value="14" name="A7XX_PERF_PC_VIS_STREAMS_LOADED"/> + <value value="15" name="A7XX_PERF_PC_INSTANCES"/> + <value value="16" name="A7XX_PERF_PC_VPC_PRIMITIVES"/> + <value value="17" name="A7XX_PERF_PC_DEAD_PRIM"/> + <value value="18" name="A7XX_PERF_PC_LIVE_PRIM"/> + <value value="19" name="A7XX_PERF_PC_VERTEX_HITS"/> + <value value="20" name="A7XX_PERF_PC_IA_VERTICES"/> + <value value="21" name="A7XX_PERF_PC_IA_PRIMITIVES"/> + <value value="22" name="A7XX_PERF_PC_RESERVED_22"/> + <value value="23" name="A7XX_PERF_PC_HS_INVOCATIONS"/> + <value value="24" name="A7XX_PERF_PC_DS_INVOCATIONS"/> + <value value="25" name="A7XX_PERF_PC_VS_INVOCATIONS"/> + <value value="26" name="A7XX_PERF_PC_GS_INVOCATIONS"/> + <value value="27" name="A7XX_PERF_PC_DS_PRIMITIVES"/> + <value value="28" name="A7XX_PERF_PC_3D_DRAWCALLS"/> + <value value="29" name="A7XX_PERF_PC_2D_DRAWCALLS"/> + <value value="30" name="A7XX_PERF_PC_NON_DRAWCALL_GLOBAL_EVENTS"/> + <value value="31" name="A7XX_PERF_PC_TESS_BUSY_CYCLES"/> + <value value="32" name="A7XX_PERF_PC_TESS_WORKING_CYCLES"/> + <value value="33" name="A7XX_PERF_PC_TESS_STALL_CYCLES_PC"/> + <value value="34" name="A7XX_PERF_PC_TESS_STARVE_CYCLES_PC"/> + <value value="35" name="A7XX_PERF_PC_TESS_SINGLE_PRIM_CYCLES"/> + <value value="36" name="A7XX_PERF_PC_TESS_PC_UV_TRANS"/> + <value value="37" name="A7XX_PERF_PC_TESS_PC_UV_PATCHES"/> + <value value="38" name="A7XX_PERF_PC_TESS_FACTOR_TRANS"/> + <value value="39" name="A7XX_PERF_PC_TAG_CHECKED_VERTICES"/> + <value value="40" name="A7XX_PERF_PC_MESH_VS_WAVES"/> + <value value="41" name="A7XX_PERF_PC_MESH_DRAWS"/> + <value value="42" name="A7XX_PERF_PC_MESH_DEAD_DRAWS"/> + <value value="43" name="A7XX_PERF_PC_MESH_MVIS_EN_DRAWS"/> + <value value="44" name="A7XX_PERF_PC_MESH_DEAD_PRIM"/> + <value value="45" name="A7XX_PERF_PC_MESH_LIVE_PRIM"/> + <value value="46" name="A7XX_PERF_PC_MESH_PA_EN_PRIM"/> + <value value="47" name="A7XX_PERF_PC_STARVE_CYCLES_FOR_MVIS_STREAM"/> + <value value="48" name="A7XX_PERF_PC_STARVE_CYCLES_PREDRAW"/> + <value value="49" name="A7XX_PERF_PC_STALL_CYCLES_COMPUTE_GFX"/> + <value value="50" name="A7XX_PERF_PC_STALL_CYCLES_GFX_COMPUTE"/> + <value value="51" name="A7XX_PERF_PC_TESS_PC_MULTI_PATCH_TRANS"/> +</enum> + +<enum name="a7xx_vfd_perfcounter_select"> + <value value="0" name="A7XX_PERF_VFD_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_VFD_STALL_CYCLES_UCHE"/> + <value value="2" name="A7XX_PERF_VFD_STALL_CYCLES_VPC_ALLOC"/> + <value value="3" name="A7XX_PERF_VFD_STALL_CYCLES_SP_INFO"/> + <value value="4" name="A7XX_PERF_VFD_STALL_CYCLES_SP_ATTR"/> + <value value="5" name="A7XX_PERF_VFD_STARVE_CYCLES_UCHE"/> + <value value="6" name="A7XX_PERF_VFD_RBUFFER_FULL"/> + <value value="7" name="A7XX_PERF_VFD_ATTR_INFO_FIFO_FULL"/> + <value value="8" name="A7XX_PERF_VFD_DECODED_ATTRIBUTE_BYTES"/> + <value value="9" name="A7XX_PERF_VFD_NUM_ATTRIBUTES"/> + <value value="10" name="A7XX_PERF_VFD_UPPER_SHADER_FIBERS"/> + <value value="11" name="A7XX_PERF_VFD_LOWER_SHADER_FIBERS"/> + <value value="12" name="A7XX_PERF_VFD_MODE_0_FIBERS"/> + <value value="13" name="A7XX_PERF_VFD_MODE_1_FIBERS"/> + <value value="14" name="A7XX_PERF_VFD_MODE_2_FIBERS"/> + <value value="15" name="A7XX_PERF_VFD_MODE_3_FIBERS"/> + <value value="16" name="A7XX_PERF_VFD_MODE_4_FIBERS"/> + <value value="17" name="A7XX_PERF_VFD_TOTAL_VERTICES"/> + <value value="18" name="A7XX_PERF_VFDP_STALL_CYCLES_VFD"/> + <value value="19" name="A7XX_PERF_VFDP_STALL_CYCLES_VFD_INDEX"/> + <value value="20" name="A7XX_PERF_VFDP_STALL_CYCLES_VFD_PROG"/> + <value value="21" name="A7XX_PERF_VFDP_STARVE_CYCLES_PC"/> + <value value="22" name="A7XX_PERF_VFDP_VS_STAGE_WAVES"/> + <value value="23" name="A7XX_PERF_VFD_STALL_CYCLES_PRG_END_FE"/> + <value value="24" name="A7XX_PERF_VFD_STALL_CYCLES_CBSYNC"/> +</enum> + +<enum name="a7xx_hlsq_perfcounter_select"> + <value value="0" name="A7XX_PERF_HLSQ_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_HLSQ_STALL_CYCLES_UCHE"/> + <value value="2" name="A7XX_PERF_HLSQ_STALL_CYCLES_SP_STATE"/> + <value value="3" name="A7XX_PERF_HLSQ_STALL_CYCLES_SP_FS_STAGE"/> + <value value="4" name="A7XX_PERF_HLSQ_UCHE_LATENCY_CYCLES"/> + <value value="5" name="A7XX_PERF_HLSQ_UCHE_LATENCY_COUNT"/> + <value value="6" name="A7XX_PERF_HLSQ_RESERVED_6"/> + <value value="7" name="A7XX_PERF_HLSQ_RESERVED_7"/> + <value value="8" name="A7XX_PERF_HLSQ_RESERVED_8"/> + <value value="9" name="A7XX_PERF_HLSQ_RESERVED_9"/> + <value value="10" name="A7XX_PERF_HLSQ_COMPUTE_DRAWCALLS"/> + <value value="11" name="A7XX_PERF_HLSQ_FS_DATA_WAIT_PROGRAMMING"/> + <value value="12" name="A7XX_PERF_HLSQ_DUAL_FS_PROG_ACTIVE"/> + <value value="13" name="A7XX_PERF_HLSQ_DUAL_VS_PROG_ACTIVE"/> + <value value="14" name="A7XX_PERF_HLSQ_FS_BATCH_COUNT_ZERO"/> + <value value="15" name="A7XX_PERF_HLSQ_VS_BATCH_COUNT_ZERO"/> + <value value="16" name="A7XX_PERF_HLSQ_WAVE_PENDING_NO_QUAD"/> + <value value="17" name="A7XX_PERF_HLSQ_WAVE_PENDING_NO_PRIM_BASE"/> + <value value="18" name="A7XX_PERF_HLSQ_STALL_CYCLES_VPC"/> + <value value="19" name="A7XX_PERF_HLSQ_RESERVED_19"/> + <value value="20" name="A7XX_PERF_HLSQ_DRAW_MODE_SWITCH_VSFS_SYNC"/> + <value value="21" name="A7XX_PERF_HLSQ_VSBR_STALL_CYCLES"/> + <value value="22" name="A7XX_PERF_HLSQ_FS_STALL_CYCLES"/> + <value value="23" name="A7XX_PERF_HLSQ_LPAC_STALL_CYCLES"/> + <value value="24" name="A7XX_PERF_HLSQ_BV_STALL_CYCLES"/> + <value value="25" name="A7XX_PERF_HLSQ_VSBR_DEREF_CYCLES"/> + <value value="26" name="A7XX_PERF_HLSQ_FS_DEREF_CYCLES"/> + <value value="27" name="A7XX_PERF_HLSQ_LPAC_DEREF_CYCLES"/> + <value value="28" name="A7XX_PERF_HLSQ_BV_DEREF_CYCLES"/> + <value value="29" name="A7XX_PERF_HLSQ_VSBR_S2W_CYCLES"/> + <value value="30" name="A7XX_PERF_HLSQ_FS_S2W_CYCLES"/> + <value value="31" name="A7XX_PERF_HLSQ_LPAC_S2W_CYCLES"/> + <value value="32" name="A7XX_PERF_HLSQ_BV_S2W_CYCLES"/> + <value value="33" name="A7XX_PERF_HLSQ_VSBR_WAIT_FS_S2W"/> + <value value="34" name="A7XX_PERF_HLSQ_FS_WAIT_VS_S2W"/> + <value value="35" name="A7XX_PERF_HLSQ_LPAC_WAIT_VS_S2W"/> + <value value="36" name="A7XX_PERF_HLSQ_BV_WAIT_FS_S2W"/> + <value value="37" name="A7XX_PERF_HLSQ_VS_WAIT_CONST_RESOURCE"/> + <value value="38" name="A7XX_PERF_HLSQ_FS_WAIT_SAME_VS_S2W"/> + <value value="39" name="A7XX_PERF_HLSQ_FS_STARVING_SP"/> + <value value="40" name="A7XX_PERF_HLSQ_VS_DATA_WAIT_PROGRAMMING"/> + <value value="41" name="A7XX_PERF_HLSQ_BV_DATA_WAIT_PROGRAMMING"/> + <value value="42" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXTS_VS"/> + <value value="43" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXT_CYCLES_VS"/> + <value value="44" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXTS_FS"/> + <value value="45" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXT_CYCLES_FS"/> + <value value="46" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXTS_BV"/> + <value value="47" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXT_CYCLES_BV"/> + <value value="48" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXTS_LPAC"/> + <value value="49" name="A7XX_PERF_HLSQ_STPROC_WAVE_CONTEXT_CYCLES_LPAC"/> + <value value="50" name="A7XX_PERF_HLSQ_SPTROC_STCHE_WARMUP_INC_VS"/> + <value value="51" name="A7XX_PERF_HLSQ_SPTROC_STCHE_WARMUP_INC_FS"/> + <value value="52" name="A7XX_PERF_HLSQ_SPTROC_STCHE_WARMUP_INC_BV"/> + <value value="53" name="A7XX_PERF_HLSQ_SPTROC_STCHE_WARMUP_INC_LPAC"/> + <value value="54" name="A7XX_PERF_HLSQ_SPTROC_STCHE_MISS_INC_VS"/> + <value value="55" name="A7XX_PERF_HLSQ_SPTROC_STCHE_MISS_INC_FS"/> + <value value="56" name="A7XX_PERF_HLSQ_SPTROC_STCHE_MISS_INC_BV"/> + <value value="57" name="A7XX_PERF_HLSQ_SPTROC_STCHE_MISS_INC_LPAC"/> +</enum> + +<enum name="a7xx_vpc_perfcounter_select"> + <value value="0" name="A7XX_PERF_VPC_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_VPC_WORKING_CYCLES"/> + <value value="2" name="A7XX_PERF_VPC_STALL_CYCLES_UCHE"/> + <value value="3" name="A7XX_PERF_VPC_STALL_CYCLES_VFD_WACK"/> + <value value="4" name="A7XX_PERF_VPC_STALL_CYCLES_HLSQ_PRIM_ALLOC"/> + <value value="5" name="A7XX_PERF_VPC_RESERVED_5"/> + <value value="6" name="A7XX_PERF_VPC_STALL_CYCLES_SP_LM"/> + <value value="7" name="A7XX_PERF_VPC_STARVE_CYCLES_SP"/> + <value value="8" name="A7XX_PERF_VPC_STARVE_CYCLES_LRZ"/> + <value value="9" name="A7XX_PERF_VPC_PC_PRIMITIVES"/> + <value value="10" name="A7XX_PERF_VPC_SP_COMPONENTS"/> + <value value="11" name="A7XX_PERF_VPC_STALL_CYCLES_VPCRAM_POS"/> + <value value="12" name="A7XX_PERF_VPC_LRZ_ASSIGN_PRIMITIVES"/> + <value value="13" name="A7XX_PERF_VPC_RB_VISIBLE_PRIMITIVES"/> + <value value="14" name="A7XX_PERF_VPC_LM_TRANSACTION"/> + <value value="15" name="A7XX_PERF_VPC_STREAMOUT_TRANSACTION"/> + <value value="16" name="A7XX_PERF_VPC_VS_BUSY_CYCLES"/> + <value value="17" name="A7XX_PERF_VPC_PS_BUSY_CYCLES"/> + <value value="18" name="A7XX_PERF_VPC_VS_WORKING_CYCLES"/> + <value value="19" name="A7XX_PERF_VPC_PS_WORKING_CYCLES"/> + <value value="20" name="A7XX_PERF_VPC_STARVE_CYCLES_RB"/> + <value value="21" name="A7XX_PERF_VPC_NUM_VPCRAM_READ_POS"/> + <value value="22" name="A7XX_PERF_VPC_WIT_FULL_CYCLES"/> + <value value="23" name="A7XX_PERF_VPC_VPCRAM_FULL_CYCLES"/> + <value value="24" name="A7XX_PERF_VPC_LM_FULL_WAIT_FOR_INTP_END"/> + <value value="25" name="A7XX_PERF_VPC_NUM_VPCRAM_WRITE"/> + <value value="26" name="A7XX_PERF_VPC_NUM_VPCRAM_READ_SO"/> + <value value="27" name="A7XX_PERF_VPC_NUM_ATTR_REQ_LM"/> + <value value="28" name="A7XX_PERF_VPC_STALL_CYCLE_TSE"/> + <value value="29" name="A7XX_PERF_VPC_TSE_PRIMITIVES"/> + <value value="30" name="A7XX_PERF_VPC_GS_PRIMITIVES"/> + <value value="31" name="A7XX_PERF_VPC_TSE_TRANSACTIONS"/> + <value value="32" name="A7XX_PERF_VPC_STALL_CYCLES_CCU"/> + <value value="33" name="A7XX_PERF_VPC_NUM_WM_HIT"/> + <value value="34" name="A7XX_PERF_VPC_STALL_DQ_WACK"/> + <value value="35" name="A7XX_PERF_VPC_STALL_CYCLES_CCHE"/> + <value value="36" name="A7XX_PERF_VPC_STARVE_CYCLES_CCHE"/> + <value value="37" name="A7XX_PERF_VPC_NUM_PA_REQ"/> + <value value="38" name="A7XX_PERF_VPC_NUM_LM_REQ_HIT"/> + <value value="39" name="A7XX_PERF_VPC_CCHE_REQBUF_FULL"/> + <value value="40" name="A7XX_PERF_VPC_STALL_CYCLES_LM_ACK"/> + <value value="41" name="A7XX_PERF_VPC_STALL_CYCLES_PRG_END_FE"/> + <value value="42" name="A7XX_PERF_VPC_STALL_CYCLES_PRG_END_PCVS"/> + <value value="43" name="A7XX_PERF_VPC_STALL_CYCLES_PRG_END_VPCPS"/> +</enum> + +<enum name="a7xx_tse_perfcounter_select"> + <value value="0" name="A7XX_PERF_TSE_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_TSE_CLIPPING_CYCLES"/> + <value value="2" name="A7XX_PERF_TSE_STALL_CYCLES_RAS"/> + <value value="3" name="A7XX_PERF_TSE_STALL_CYCLES_LRZ_BARYPLANE"/> + <value value="4" name="A7XX_PERF_TSE_STALL_CYCLES_LRZ_ZPLANE"/> + <value value="5" name="A7XX_PERF_TSE_STARVE_CYCLES_PC"/> + <value value="6" name="A7XX_PERF_TSE_INPUT_PRIM"/> + <value value="7" name="A7XX_PERF_TSE_INPUT_NULL_PRIM"/> + <value value="8" name="A7XX_PERF_TSE_TRIVAL_REJ_PRIM"/> + <value value="9" name="A7XX_PERF_TSE_CLIPPED_PRIM"/> + <value value="10" name="A7XX_PERF_TSE_ZERO_AREA_PRIM"/> + <value value="11" name="A7XX_PERF_TSE_FACENESS_CULLED_PRIM"/> + <value value="12" name="A7XX_PERF_TSE_ZERO_PIXEL_PRIM"/> + <value value="13" name="A7XX_PERF_TSE_OUTPUT_NULL_PRIM"/> + <value value="14" name="A7XX_PERF_TSE_OUTPUT_VISIBLE_PRIM"/> + <value value="15" name="A7XX_PERF_TSE_CINVOCATION"/> + <value value="16" name="A7XX_PERF_TSE_CPRIMITIVES"/> + <value value="17" name="A7XX_PERF_TSE_2D_INPUT_PRIM"/> + <value value="18" name="A7XX_PERF_TSE_2D_ALIVE_CYCLES"/> + <value value="19" name="A7XX_PERF_TSE_CLIP_PLANES"/> +</enum> + +<enum name="a7xx_ras_perfcounter_select"> + <value value="0" name="A7XX_PERF_RAS_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_RAS_SUPERTILE_ACTIVE_CYCLES"/> + <value value="2" name="A7XX_PERF_RAS_STALL_CYCLES_LRZ"/> + <value value="3" name="A7XX_PERF_RAS_STARVE_CYCLES_TSE"/> + <value value="4" name="A7XX_PERF_RAS_SUPER_TILES"/> + <value value="5" name="A7XX_PERF_RAS_8X4_TILES"/> + <value value="6" name="A7XX_PERF_RAS_MASKGEN_ACTIVE"/> + <value value="7" name="A7XX_PERF_RAS_FULLY_COVERED_SUPER_TILES"/> + <value value="8" name="A7XX_PERF_RAS_FULLY_COVERED_8X4_TILES"/> + <value value="9" name="A7XX_PERF_RAS_PRIM_KILLED_INVISILBE"/> + <value value="10" name="A7XX_PERF_RAS_SUPERTILE_GEN_ACTIVE_CYCLES"/> + <value value="11" name="A7XX_PERF_RAS_LRZ_INTF_WORKING_CYCLES"/> + <value value="12" name="A7XX_PERF_RAS_BLOCKS"/> + <value value="13" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_0_WORKING_CC_l2"/> + <value value="14" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_1_WORKING_CC_l2"/> + <value value="15" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_2_WORKING_CC_l2"/> + <value value="16" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_3_WORKING_CC_l2"/> + <value value="17" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_4_WORKING_CC_l2"/> + <value value="18" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_5_WORKING_CC_l2"/> + <value value="19" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_6_WORKING_CC_l2"/> + <value value="20" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_7_WORKING_CC_l2"/> + <value value="21" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_8_WORKING_CC_l2"/> + <value value="22" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_9_WORKING_CC_l2"/> + <value value="23" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_10_WORKING_CC_l2"/> + <value value="24" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_11_WORKING_CC_l2"/> + <value value="25" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_12_WORKING_CC_l2"/> + <value value="26" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_13_WORKING_CC_l2"/> + <value value="27" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_14_WORKING_CC_l2"/> + <value value="28" name="A7XX_PERF_RAS_SAMPLE_MASK_GEN_LANE_15_WORKING_CC_l2"/> + <value value="29" name="A7XX_PERF_RAS_FALSE_PARTIAL_STILE"/> + +</enum> + +<enum name="a7xx_uche_perfcounter_select"> + <value value="0" name="A7XX_PERF_UCHE_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_UCHE_STALL_CYCLES_ARBITER"/> + <value value="2" name="A7XX_PERF_UCHE_VBIF_LATENCY_CYCLES"/> + <value value="3" name="A7XX_PERF_UCHE_VBIF_LATENCY_SAMPLES"/> + <value value="4" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_TP"/> + <value value="5" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_VFD"/> + <value value="6" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_HLSQ"/> + <value value="7" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_LRZ"/> + <value value="8" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_SP"/> + <value value="9" name="A7XX_PERF_UCHE_READ_REQUESTS_TP"/> + <value value="10" name="A7XX_PERF_UCHE_READ_REQUESTS_VFD"/> + <value value="11" name="A7XX_PERF_UCHE_READ_REQUESTS_HLSQ"/> + <value value="12" name="A7XX_PERF_UCHE_READ_REQUESTS_LRZ"/> + <value value="13" name="A7XX_PERF_UCHE_READ_REQUESTS_SP"/> + <value value="14" name="A7XX_PERF_UCHE_WRITE_REQUESTS_LRZ"/> + <value value="15" name="A7XX_PERF_UCHE_WRITE_REQUESTS_SP"/> + <value value="16" name="A7XX_PERF_UCHE_WRITE_REQUESTS_VPC"/> + <value value="17" name="A7XX_PERF_UCHE_WRITE_REQUESTS_VSC"/> + <value value="18" name="A7XX_PERF_UCHE_EVICTS"/> + <value value="19" name="A7XX_PERF_UCHE_BANK_REQ0"/> + <value value="20" name="A7XX_PERF_UCHE_BANK_REQ1"/> + <value value="21" name="A7XX_PERF_UCHE_BANK_REQ2"/> + <value value="22" name="A7XX_PERF_UCHE_BANK_REQ3"/> + <value value="23" name="A7XX_PERF_UCHE_BANK_REQ4"/> + <value value="24" name="A7XX_PERF_UCHE_BANK_REQ5"/> + <value value="25" name="A7XX_PERF_UCHE_BANK_REQ6"/> + <value value="26" name="A7XX_PERF_UCHE_BANK_REQ7"/> + <value value="27" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_CH0"/> + <value value="28" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_CH1"/> + <value value="29" name="A7XX_PERF_UCHE_GMEM_READ_BEATS"/> + <value value="30" name="A7XX_PERF_UCHE_TPH_REF_FULL"/> + <value value="31" name="A7XX_PERF_UCHE_TPH_VICTIM_FULL"/> + <value value="32" name="A7XX_PERF_UCHE_TPH_EXT_FULL"/> + <value value="33" name="A7XX_PERF_UCHE_VBIF_STALL_WRITE_DATA"/> + <value value="34" name="A7XX_PERF_UCHE_DCMP_LATENCY_SAMPLES"/> + <value value="35" name="A7XX_PERF_UCHE_DCMP_LATENCY_CYCLES"/> + <value value="36" name="A7XX_PERF_UCHE_VBIF_READ_BEATS_PC"/> + <value value="37" name="A7XX_PERF_UCHE_READ_REQUESTS_PC"/> + <value value="38" name="A7XX_PERF_UCHE_RAM_READ_REQ"/> + <value value="39" name="A7XX_PERF_UCHE_RAM_WRITE_REQ"/> + <value value="40" name="A7XX_PERF_UCHE_STARVED_CYCLES_VBIF_DECMP"/> + <value value="41" name="A7XX_PERF_UCHE_STALL_CYCLES_DECMP"/> + <value value="42" name="A7XX_PERF_UCHE_ARBITER_STALL_CYCLES_VBIF"/> + <value value="43" name="A7XX_PERF_UCHE_READ_REQUESTS_TP_UBWC"/> + <value value="44" name="A7XX_PERF_UCHE_READ_REQUESTS_TP_NONUBWC"/> + <value value="45" name="A7XX_PERF_UCHE_READ_REQUESTS_TP_GMEM"/> + <value value="46" name="A7XX_PERF_UCHE_LONG_LINE_ALL_EVICTS_KAILUA"/> + <value value="47" name="A7XX_PERF_UCHE_LONG_LINE_PARTIAL_EVICTS_KAILUA"/> + <value value="48" name="A7XX_PERF_UCHE_TPH_CONFLICT_CL_CCHE"/> + <value value="49" name="A7XX_PERF_UCHE_TPH_CONFLICT_CL_OTHER_KAILUA"/> + <value value="50" name="A7XX_PERF_UCHE_DBANK_CONFLICT_CL_CCHE"/> + <value value="51" name="A7XX_PERF_UCHE_DBANK_CONFLICT_CL_OTHER_CLIENTS"/> + <value value="52" name="A7XX_PERF_UCHE_VBIF_WRITE_BEATS_CH0"/> + <value value="53" name="A7XX_PERF_UCHE_VBIF_WRITE_BEATS_CH1"/> + <value value="54" name="A7XX_PERF_UCHE_CCHE_TPH_QUEUE_FULL"/> + <value value="55" name="A7XX_PERF_UCHE_CCHE_DPH_QUEUE_FULL"/> + <value value="56" name="A7XX_PERF_UCHE_GMEM_WRITE_BEATS"/> + <value value="57" name="A7XX_PERF_UCHE_UBWC_READ_BEATS"/> + <value value="58" name="A7XX_PERF_UCHE_UBWC_WRITE_BEATS"/> +</enum> + +<enum name="a7xx_tp_perfcounter_select"> + <value value="0" name="A7XX_PERF_TP_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_TP_STALL_CYCLES_UCHE"/> + <value value="2" name="A7XX_PERF_TP_LATENCY_CYCLES"/> + <value value="3" name="A7XX_PERF_TP_LATENCY_TRANS"/> + <value value="4" name="A7XX_PERF_TP_FLAG_FIFO_DELAY_SAMPLES"/> + <value value="5" name="A7XX_PERF_TP_FLAG_FIFO_DELAY_CYCLES"/> + <value value="6" name="A7XX_PERF_TP_L1_CACHELINE_REQUESTS"/> + <value value="7" name="A7XX_PERF_TP_L1_CACHELINE_MISSES"/> + <value value="8" name="A7XX_PERF_TP_SP_TP_TRANS"/> + <value value="9" name="A7XX_PERF_TP_TP_SP_TRANS"/> + <value value="10" name="A7XX_PERF_TP_OUTPUT_PIXELS"/> + <value value="11" name="A7XX_PERF_TP_FILTER_WORKLOAD_16BIT"/> + <value value="12" name="A7XX_PERF_TP_FILTER_WORKLOAD_32BIT"/> + <value value="13" name="A7XX_PERF_TP_QUADS_RECEIVED"/> + <value value="14" name="A7XX_PERF_TP_QUADS_OFFSET"/> + <value value="15" name="A7XX_PERF_TP_QUADS_SHADOW"/> + <value value="16" name="A7XX_PERF_TP_QUADS_ARRAY"/> + <value value="17" name="A7XX_PERF_TP_QUADS_GRADIENT"/> + <value value="18" name="A7XX_PERF_TP_QUADS_1D"/> + <value value="19" name="A7XX_PERF_TP_QUADS_2D"/> + <value value="20" name="A7XX_PERF_TP_QUADS_BUFFER"/> + <value value="21" name="A7XX_PERF_TP_QUADS_3D"/> + <value value="22" name="A7XX_PERF_TP_QUADS_CUBE"/> + <value value="23" name="A7XX_PERF_TP_DIVERGENT_QUADS_RECEIVED"/> + <value value="24" name="A7XX_PERF_TP_PRT_NON_RESIDENT_EVENTS"/> + <value value="25" name="A7XX_PERF_TP_OUTPUT_PIXELS_POINT"/> + <value value="26" name="A7XX_PERF_TP_OUTPUT_PIXELS_BILINEAR"/> + <value value="27" name="A7XX_PERF_TP_OUTPUT_PIXELS_MIP"/> + <value value="28" name="A7XX_PERF_TP_OUTPUT_PIXELS_ANISO"/> + <value value="29" name="A7XX_PERF_TP_OUTPUT_PIXELS_ZERO_LOD"/> + <value value="30" name="A7XX_PERF_TP_FLAG_CACHE_REQUESTS"/> + <value value="31" name="A7XX_PERF_TP_FLAG_CACHE_MISSES"/> + <value value="32" name="A7XX_PERF_TP_L1_5_L2_REQUESTS"/> + <value value="33" name="A7XX_PERF_TP_2D_OUTPUT_PIXELS"/> + <value value="34" name="A7XX_PERF_TP_2D_OUTPUT_PIXELS_POINT"/> + <value value="35" name="A7XX_PERF_TP_2D_OUTPUT_PIXELS_BILINEAR"/> + <value value="36" name="A7XX_PERF_TP_2D_FILTER_WORKLOAD_16BIT"/> + <value value="37" name="A7XX_PERF_TP_2D_FILTER_WORKLOAD_32BIT"/> + <value value="38" name="A7XX_PERF_TP_TPA2TPC_TRANS"/> + <value value="39" name="A7XX_PERF_TP_L1_MISSES_ASTC_1TILE"/> + <value value="40" name="A7XX_PERF_TP_L1_MISSES_ASTC_2TILE"/> + <value value="41" name="A7XX_PERF_TP_L1_MISSES_ASTC_4TILE"/> + <value value="42" name="A7XX_PERF_TP_L1_5_COMPRESS_REQS"/> + <value value="43" name="A7XX_PERF_TP_L1_5_L2_COMPRESS_MISS"/> + <value value="44" name="A7XX_PERF_TP_L1_BANK_CONFLICT"/> + <value value="45" name="A7XX_PERF_TP_L1_5_MISS_LATENCY_CYCLES"/> + <value value="46" name="A7XX_PERF_TP_L1_5_MISS_LATENCY_TRANS"/> + <value value="47" name="A7XX_PERF_TP_QUADS_CONSTANT_MULTIPLIED"/> + <value value="48" name="A7XX_PERF_TP_FRONTEND_WORKING_CYCLES"/> + <value value="49" name="A7XX_PERF_TP_L1_TAG_WORKING_CYCLES"/> + <value value="50" name="A7XX_PERF_TP_L1_DATA_WRITE_WORKING_CYCLES"/> + <value value="51" name="A7XX_PERF_TP_PRE_L1_DECOM_WORKING_CYCLES"/> + <value value="52" name="A7XX_PERF_TP_BACKEND_WORKING_CYCLES"/> + <value value="53" name="A7XX_PERF_TP_L1_5_CACHE_WORKING_CYCLES"/> + <value value="54" name="A7XX_PERF_TP_STARVE_CYCLES_SP"/> + <value value="55" name="A7XX_PERF_TP_STARVE_CYCLES_UCHE"/> + <value value="56" name="A7XX_PERF_TP_STALL_CYCLES_UFC"/> + <value value="57" name="A7XX_PERF_TP_FORMAT_DECOMP"/> + <value value="58" name="A7XX_PERF_TP_FILTER_POINT_FP16"/> + <value value="59" name="A7XX_PERF_TP_FILTER_POINT_FP32"/> + <value value="60" name="A7XX_PERF_TP_LATENCY_FIFO_FULL"/> + <value value="61" name="A7XX_PERF_TP_RESERVED_61"/> + <value value="62" name="A7XX_PERF_TP_RESERVED_62"/> + <value value="63" name="A7XX_PERF_TP_RESERVED_63"/> + <value value="64" name="A7XX_PERF_TP_RESERVED_64"/> + <value value="65" name="A7XX_PERF_TP_RESERVED_65"/> + <value value="66" name="A7XX_PERF_TP_RESERVED_66"/> + <value value="67" name="A7XX_PERF_TP_RESERVED_67"/> + <value value="68" name="A7XX_PERF_TP_RESERVED_68"/> + <value value="69" name="A7XX_PERF_TP_RESERVED_69"/> + <value value="70" name="A7XX_PERF_TP_RESERVED_70"/> + <value value="71" name="A7XX_PERF_TP_RESERVED_71"/> + <value value="72" name="A7XX_PERF_TP_RESERVED_72"/> + <value value="73" name="A7XX_PERF_TP_RESERVED_73"/> + <value value="74" name="A7XX_PERF_TP_RESERVED_74"/> + <value value="75" name="A7XX_PERF_TP_RESERVED_75"/> + <value value="76" name="A7XX_PERF_TP_RESERVED_76"/> + <value value="77" name="A7XX_PERF_TP_RESERVED_77"/> + <value value="78" name="A7XX_PERF_TP_RESERVED_78"/> + <value value="79" name="A7XX_PERF_TP_RESERVED_79"/> + <value value="80" name="A7XX_PERF_TP_RESERVED_80"/> + <value value="81" name="A7XX_PERF_TP_RESERVED_81"/> + <value value="82" name="A7XX_PERF_TP_RESERVED_82"/> + <value value="83" name="A7XX_PERF_TP_RESERVED_83"/> + <value value="84" name="A7XX_PERF_TP_RESERVED_84"/> + <value value="85" name="A7XX_PERF_TP_RESERVED_85"/> + <value value="86" name="A7XX_PERF_TP_RESERVED_86"/> + <value value="87" name="A7XX_PERF_TP_RESERVED_87"/> + <value value="88" name="A7XX_PERF_TP_RESERVED_88"/> + <value value="89" name="A7XX_PERF_TP_RESERVED_89"/> + <value value="90" name="A7XX_PERF_TP_RESERVED_90"/> + <value value="91" name="A7XX_PERF_TP_RESERVED_91"/> + <value value="92" name="A7XX_PERF_TP_RESERVED_92"/> + <value value="93" name="A7XX_PERF_TP_RESERVED_93"/> + <value value="94" name="A7XX_PERF_TP_RESERVED_94"/> + <value value="95" name="A7XX_PERF_TP_RESERVED_95"/> + <value value="96" name="A7XX_PERF_TP_RESERVED_96"/> + <value value="97" name="A7XX_PERF_TP_RESERVED_97"/> + <value value="98" name="A7XX_PERF_TP_RESERVED_98"/> + <value value="99" name="A7XX_PERF_TP_RESERVED_99"/> + <value value="100" name="A7XX_PERF_TP_RESERVED_100"/> + <value value="101" name="A7XX_PERF_TP_RESERVED_101"/> + <value value="102" name="A7XX_PERF_TP_RESERVED_102"/> + <value value="103" name="A7XX_PERF_TP_RESERVED_103"/> + <value value="104" name="A7XX_PERF_TP_RESERVED_104"/> + <value value="105" name="A7XX_PERF_TP_RESERVED_105"/> + <value value="106" name="A7XX_PERF_TP_RESERVED_106"/> + <value value="107" name="A7XX_PERF_TP_RESERVED_107"/> + <value value="108" name="A7XX_PERF_TP_RESERVED_108"/> + <value value="109" name="A7XX_PERF_TP_RESERVED_109"/> + <value value="110" name="A7XX_PERF_TP_RESERVED_110"/> + <value value="111" name="A7XX_PERF_TP_RESERVED_111"/> + <value value="112" name="A7XX_PERF_TP_RESERVED_112"/> + <value value="113" name="A7XX_PERF_TP_RESERVED_113"/> + <value value="114" name="A7XX_PERF_TP_RESERVED_114"/> + <value value="115" name="A7XX_PERF_TP_RESERVED_115"/> + <value value="116" name="A7XX_PERF_TP_RESERVED_116"/> + <value value="117" name="A7XX_PERF_TP_RESERVED_117"/> + <value value="118" name="A7XX_PERF_TP_RESERVED_118"/> + <value value="119" name="A7XX_PERF_TP_RESERVED_119"/> + <value value="120" name="A7XX_PERF_TP_RESERVED_120"/> + <value value="121" name="A7XX_PERF_TP_RESERVED_121"/> + <value value="122" name="A7XX_PERF_TP_RESERVED_122"/> + <value value="123" name="A7XX_PERF_TP_RESERVED_123"/> + <value value="124" name="A7XX_PERF_TP_RESERVED_124"/> + <value value="125" name="A7XX_PERF_TP_RESERVED_125"/> + <value value="126" name="A7XX_PERF_TP_RESERVED_126"/> + <value value="127" name="A7XX_PERF_TP_RESERVED_127"/> + <value value="128" name="A7XX_PERF_TP_FORMAT_DECOMP_BILINEAR"/> + <value value="129" name="A7XX_PERF_TP_PACKED_POINT_BOTH_VALID_FP16"/> + <value value="130" name="A7XX_PERF_TP_PACKED_POINT_SINGLE_VALID_FP16"/> + <value value="131" name="A7XX_PERF_TP_PACKED_POINT_BOTH_VALID_FP32"/> + <value value="132" name="A7XX_PERF_TP_PACKED_POINT_SINGLE_VALID_FP32"/> +</enum> + +<enum name="a7xx_sp_perfcounter_select"> + <value value="0" name="A7XX_PERF_SP_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_SP_ALU_WORKING_CYCLES"/> + <value value="2" name="A7XX_PERF_SP_EFU_WORKING_CYCLES"/> + <value value="3" name="A7XX_PERF_SP_STALL_CYCLES_VPC"/> + <value value="4" name="A7XX_PERF_SP_STALL_CYCLES_TP"/> + <value value="5" name="A7XX_PERF_SP_STALL_CYCLES_UCHE"/> + <value value="6" name="A7XX_PERF_SP_STALL_CYCLES_RB"/> + <value value="7" name="A7XX_PERF_SP_NON_EXECUTION_CYCLES"/> + <value value="8" name="A7XX_PERF_SP_WAVE_CONTEXTS"/> + <value value="9" name="A7XX_PERF_SP_WAVE_CONTEXT_CYCLES"/> + <value value="10" name="A7XX_PERF_SP_STAGE_WAVE_CYCLES"/> + <value value="11" name="A7XX_PERF_SP_STAGE_WAVE_SAMPLES"/> + <value value="12" name="A7XX_PERF_SP_VS_STAGE_WAVE_CYCLES"/> + <value value="13" name="A7XX_PERF_SP_VS_STAGE_WAVE_SAMPLES"/> + <value value="14" name="A7XX_PERF_SP_FS_STAGE_DURATION_CYCLES"/> + <value value="15" name="A7XX_PERF_SP_VS_STAGE_DURATION_CYCLES"/> + <value value="16" name="A7XX_PERF_SP_WAVE_CTRL_CYCLES"/> + <value value="17" name="A7XX_PERF_SP_WAVE_LOAD_CYCLES"/> + <value value="18" name="A7XX_PERF_SP_WAVE_EMIT_CYCLES"/> + <value value="19" name="A7XX_PERF_SP_WAVE_NOP_CYCLES"/> + <value value="20" name="A7XX_PERF_SP_WAVE_WAIT_CYCLES"/> + <value value="21" name="A7XX_PERF_SP_WAVE_FETCH_CYCLES"/> + <value value="22" name="A7XX_PERF_SP_WAVE_IDLE_CYCLES"/> + <value value="23" name="A7XX_PERF_SP_WAVE_END_CYCLES"/> + <value value="24" name="A7XX_PERF_SP_WAVE_LONG_SYNC_CYCLES"/> + <value value="25" name="A7XX_PERF_SP_WAVE_SHORT_SYNC_CYCLES"/> + <value value="26" name="A7XX_PERF_SP_WAVE_JOIN_CYCLES"/> + <value value="27" name="A7XX_PERF_SP_LM_LOAD_INSTRUCTIONS"/> + <value value="28" name="A7XX_PERF_SP_LM_STORE_INSTRUCTIONS"/> + <value value="29" name="A7XX_PERF_SP_LM_ATOMICS"/> + <value value="30" name="A7XX_PERF_SP_GM_LOAD_INSTRUCTIONS"/> + <value value="31" name="A7XX_PERF_SP_GM_STORE_INSTRUCTIONS"/> + <value value="32" name="A7XX_PERF_SP_GM_ATOMICS"/> + <value value="33" name="A7XX_PERF_SP_VS_STAGE_TEX_INSTRUCTIONS"/> + <value value="34" name="A7XX_PERF_SP_VS_STAGE_EFU_INSTRUCTIONS"/> + <value value="35" name="A7XX_PERF_SP_VS_STAGE_FULL_ALU_INSTRUCTIONS"/> + <value value="36" name="A7XX_PERF_SP_VS_STAGE_HALF_ALU_INSTRUCTIONS"/> + <value value="37" name="A7XX_PERF_SP_FS_STAGE_TEX_INSTRUCTIONS"/> + <value value="38" name="A7XX_PERF_SP_FS_STAGE_CFLOW_INSTRUCTIONS"/> + <value value="39" name="A7XX_PERF_SP_FS_STAGE_EFU_INSTRUCTIONS"/> + <value value="40" name="A7XX_PERF_SP_FS_STAGE_FULL_ALU_INSTRUCTIONS"/> + <value value="41" name="A7XX_PERF_SP_FS_STAGE_HALF_ALU_INSTRUCTIONS"/> + <value value="42" name="A7XX_PERF_SP_FS_STAGE_BARY_INSTRUCTIONS"/> + <value value="43" name="A7XX_PERF_SP_VS_INSTRUCTIONS"/> + <value value="44" name="A7XX_PERF_SP_FS_INSTRUCTIONS"/> + <value value="45" name="A7XX_PERF_SP_ADDR_LOCK_COUNT"/> + <value value="46" name="A7XX_PERF_SP_UCHE_READ_TRANS"/> + <value value="47" name="A7XX_PERF_SP_UCHE_WRITE_TRANS"/> + <value value="48" name="A7XX_PERF_SP_EXPORT_VPC_TRANS"/> + <value value="49" name="A7XX_PERF_SP_EXPORT_RB_TRANS"/> + <value value="50" name="A7XX_PERF_SP_PIXELS_KILLED"/> + <value value="51" name="A7XX_PERF_SP_ICL1_REQUESTS"/> + <value value="52" name="A7XX_PERF_SP_ICL1_MISSES"/> + <value value="53" name="A7XX_PERF_SP_HS_INSTRUCTIONS"/> + <value value="54" name="A7XX_PERF_SP_DS_INSTRUCTIONS"/> + <value value="55" name="A7XX_PERF_SP_GS_INSTRUCTIONS"/> + <value value="56" name="A7XX_PERF_SP_CS_INSTRUCTIONS"/> + <value value="57" name="A7XX_PERF_SP_GPR_READ"/> + <value value="58" name="A7XX_PERF_SP_GPR_WRITE"/> + <value value="59" name="A7XX_PERF_SP_FS_STAGE_HALF_EFU_INSTRUCTIONS"/> + <value value="60" name="A7XX_PERF_SP_VS_STAGE_HALF_EFU_INSTRUCTIONS"/> + <value value="61" name="A7XX_PERF_SP_LM_BANK_CONFLICTS"/> + <value value="62" name="A7XX_PERF_SP_TEX_CONTROL_WORKING_CYCLES"/> + <value value="63" name="A7XX_PERF_SP_LOAD_CONTROL_WORKING_CYCLES"/> + <value value="64" name="A7XX_PERF_SP_FLOW_CONTROL_WORKING_CYCLES"/> + <value value="65" name="A7XX_PERF_SP_LM_WORKING_CYCLES"/> + <value value="66" name="A7XX_PERF_SP_DISPATCHER_WORKING_CYCLES"/> + <value value="67" name="A7XX_PERF_SP_SEQUENCER_WORKING_CYCLES"/> + <value value="68" name="A7XX_PERF_SP_LOW_EFFICIENCY_STARVED_BY_TP"/> + <value value="69" name="A7XX_PERF_SP_STARVE_CYCLES_HLSQ"/> + <value value="70" name="A7XX_PERF_SP_NON_EXECUTION_LS_CYCLES"/> + <value value="71" name="A7XX_PERF_SP_WORKING_EU"/> + <value value="72" name="A7XX_PERF_SP_ANY_EU_WORKING"/> + <value value="73" name="A7XX_PERF_SP_WORKING_EU_FS_STAGE"/> + <value value="74" name="A7XX_PERF_SP_ANY_EU_WORKING_FS_STAGE"/> + <value value="75" name="A7XX_PERF_SP_WORKING_EU_VS_STAGE"/> + <value value="76" name="A7XX_PERF_SP_ANY_EU_WORKING_VS_STAGE"/> + <value value="77" name="A7XX_PERF_SP_WORKING_EU_CS_STAGE"/> + <value value="78" name="A7XX_PERF_SP_ANY_EU_WORKING_CS_STAGE"/> + <value value="79" name="A7XX_PERF_SP_GPR_READ_PREFETCH"/> + <value value="80" name="A7XX_PERF_SP_GPR_READ_CONFLICT"/> + <value value="81" name="A7XX_PERF_SP_GPR_WRITE_CONFLICT"/> + <value value="82" name="A7XX_PERF_SP_GM_LOAD_LATENCY_CYCLES"/> + <value value="83" name="A7XX_PERF_SP_GM_LOAD_LATENCY_SAMPLES"/> + <value value="84" name="A7XX_PERF_SP_EXECUTABLE_WAVES"/> + <value value="85" name="A7XX_PERF_SP_ICL1_MISS_FETCH_CYCLES"/> + <value value="86" name="A7XX_PERF_SP_WORKING_EU_LPAC"/> + <value value="87" name="A7XX_PERF_SP_BYPASS_BUSY_CYCLES"/> + <value value="88" name="A7XX_PERF_SP_ANY_EU_WORKING_LPAC"/> + <value value="89" name="A7XX_PERF_SP_WAVE_ALU_CYCLES"/> + <value value="90" name="A7XX_PERF_SP_WAVE_EFU_CYCLES"/> + <value value="91" name="A7XX_PERF_SP_WAVE_INT_CYCLES"/> + <value value="92" name="A7XX_PERF_SP_WAVE_CSP_CYCLES"/> + <value value="93" name="A7XX_PERF_SP_EWAVE_CONTEXTS"/> + <value value="94" name="A7XX_PERF_SP_EWAVE_CONTEXT_CYCLES"/> + <value value="95" name="A7XX_PERF_SP_LPAC_BUSY_CYCLES"/> + <value value="96" name="A7XX_PERF_SP_LPAC_INSTRUCTIONS"/> + <value value="97" name="A7XX_PERF_SP_FS_STAGE_1X_WAVES"/> + <value value="98" name="A7XX_PERF_SP_FS_STAGE_2X_WAVES"/> + <value value="99" name="A7XX_PERF_SP_QUADS"/> + <value value="100" name="A7XX_PERF_SP_CS_INVOCATIONS"/> + <value value="101" name="A7XX_PERF_SP_PIXELS"/> + <value value="102" name="A7XX_PERF_SP_LPAC_DRAWCALLS"/> + <value value="103" name="A7XX_PERF_SP_PI_WORKING_CYCLES"/> + <value value="104" name="A7XX_PERF_SP_WAVE_INPUT_CYCLES"/> + <value value="105" name="A7XX_PERF_SP_WAVE_OUTPUT_CYCLES"/> + <value value="106" name="A7XX_PERF_SP_WAVE_HWAVE_WAIT_CYCLES"/> + <value value="107" name="A7XX_PERF_SP_WAVE_HWAVE_SYNC"/> + <value value="108" name="A7XX_PERF_SP_OUTPUT_3D_PIXELS"/> + <value value="109" name="A7XX_PERF_SP_FULL_ALU_MAD_INSTRUCTIONS"/> + <value value="110" name="A7XX_PERF_SP_HALF_ALU_MAD_INSTRUCTIONS"/> + <value value="111" name="A7XX_PERF_SP_FULL_ALU_MUL_INSTRUCTIONS"/> + <value value="112" name="A7XX_PERF_SP_HALF_ALU_MUL_INSTRUCTIONS"/> + <value value="113" name="A7XX_PERF_SP_FULL_ALU_ADD_INSTRUCTIONS"/> + <value value="114" name="A7XX_PERF_SP_HALF_ALU_ADD_INSTRUCTIONS"/> + <value value="115" name="A7XX_PERF_SP_BARY_FP32_INSTRUCTIONS"/> + <value value="116" name="A7XX_PERF_SP_ALU_GPR_READ_CYCLES"/> + <value value="117" name="A7XX_PERF_SP_ALU_DATA_FORWARDING_CYCLES"/> + <value value="118" name="A7XX_PERF_SP_LM_FULL_CYCLES"/> + <value value="119" name="A7XX_PERF_SP_TEXTURE_FETCH_LATENCY_CYCLES"/> + <value value="120" name="A7XX_PERF_SP_TEXTURE_FETCH_LATENCY_SAMPLES"/> + <value value="121" name="A7XX_PERF_SP_FS_STAGE_PI_TEX_INSTRUCTION"/> + <value value="122" name="A7XX_PERF_SP_RAY_QUERY_INSTRUCTIONS"/> + <value value="123" name="A7XX_PERF_SP_RBRT_KICKOFF_FIBERS"/> + <value value="124" name="A7XX_PERF_SP_RBRT_KICKOFF_DQUADS"/> + <value value="125" name="A7XX_PERF_SP_RTU_BUSY_CYCLES"/> + <value value="126" name="A7XX_PERF_SP_RTU_L0_HITS"/> + <value value="127" name="A7XX_PERF_SP_RTU_L0_MISSES"/> + <value value="128" name="A7XX_PERF_SP_RTU_L0_HIT_ON_MISS"/> + <value value="129" name="A7XX_PERF_SP_RTU_STALL_CYCLES_WAVE_QUEUE"/> + <value value="130" name="A7XX_PERF_SP_RTU_STALL_CYCLES_L0_HIT_QUEUE"/> + <value value="131" name="A7XX_PERF_SP_RTU_STALL_CYCLES_L0_MISS_QUEUE"/> + <value value="132" name="A7XX_PERF_SP_RTU_STALL_CYCLES_L0D_IDX_QUEUE"/> + <value value="133" name="A7XX_PERF_SP_RTU_STALL_CYCLES_L0DATA"/> + <value value="134" name="A7XX_PERF_SP_RTU_STALL_CYCLES_REPLACE_CNT"/> + <value value="135" name="A7XX_PERF_SP_RTU_STALL_CYCLES_MRG_CNT"/> + <value value="136" name="A7XX_PERF_SP_RTU_STALL_CYCLES_UCHE"/> + <value value="137" name="A7XX_PERF_SP_RTU_OPERAND_FETCH_STALL_CYCLES_L0"/> + <value value="138" name="A7XX_PERF_SP_RTU_OPERAND_FETCH_STALL_CYCLES_INS_FIFO"/> + <value value="139" name="A7XX_PERF_SP_RTU_BVH_FETCH_LATENCY_CYCLES"/> + <value value="140" name="A7XX_PERF_SP_RTU_BVH_FETCH_LATENCY_SAMPLES"/> + <value value="141" name="A7XX_PERF_SP_STCHE_MISS_INC_VS"/> + <value value="142" name="A7XX_PERF_SP_STCHE_MISS_INC_FS"/> + <value value="143" name="A7XX_PERF_SP_STCHE_MISS_INC_BV"/> + <value value="144" name="A7XX_PERF_SP_STCHE_MISS_INC_LPAC"/> + <value value="145" name="A7XX_PERF_SP_VGPR_ACTIVE_CONTEXTS"/> + <value value="146" name="A7XX_PERF_SP_PGPR_ALLOC_CONTEXTS"/> + <value value="147" name="A7XX_PERF_SP_VGPR_ALLOC_CONTEXTS"/> + <value value="148" name="A7XX_PERF_SP_RTU_RAY_BOX_INTERSECTIONS"/> + <value value="149" name="A7XX_PERF_SP_RTU_RAY_TRIANGLE_INTERSECTIONS"/> + <value value="150" name="A7XX_PERF_SP_SCH_STALL_CYCLES_RTU"/> +</enum> + +<enum name="a7xx_rb_perfcounter_select"> + <value value="0" name="A7XX_PERF_RB_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_RB_STALL_CYCLES_HLSQ"/> + <value value="2" name="A7XX_PERF_RB_STALL_CYCLES_FIFO0_FULL"/> + <value value="3" name="A7XX_PERF_RB_STALL_CYCLES_FIFO1_FULL"/> + <value value="4" name="A7XX_PERF_RB_STALL_CYCLES_FIFO2_FULL"/> + <value value="5" name="A7XX_PERF_RB_STARVE_CYCLES_SP"/> + <value value="6" name="A7XX_PERF_RB_STARVE_CYCLES_LRZ_TILE"/> + <value value="7" name="A7XX_PERF_RB_STARVE_CYCLES_CCU"/> + <value value="8" name="A7XX_PERF_RB_STARVE_CYCLES_Z_PLANE"/> + <value value="9" name="A7XX_PERF_RB_STARVE_CYCLES_BARY_PLANE"/> + <value value="10" name="A7XX_PERF_RB_Z_WORKLOAD"/> + <value value="11" name="A7XX_PERF_RB_HLSQ_ACTIVE"/> + <value value="12" name="A7XX_PERF_RB_Z_READ"/> + <value value="13" name="A7XX_PERF_RB_Z_WRITE"/> + <value value="14" name="A7XX_PERF_RB_C_READ"/> + <value value="15" name="A7XX_PERF_RB_C_WRITE"/> + <value value="16" name="A7XX_PERF_RB_TOTAL_PASS"/> + <value value="17" name="A7XX_PERF_RB_Z_PASS"/> + <value value="18" name="A7XX_PERF_RB_Z_FAIL"/> + <value value="19" name="A7XX_PERF_RB_S_FAIL"/> + <value value="20" name="A7XX_PERF_RB_BLENDED_FXP_COMPONENTS"/> + <value value="21" name="A7XX_PERF_RB_BLENDED_FP16_COMPONENTS"/> + <value value="22" name="A7XX_PERF_RB_PS_INVOCATIONS"/> + <value value="23" name="A7XX_PERF_RB_2D_ALIVE_CYCLES"/> + <value value="24" name="A7XX_PERF_RB_2D_STALL_CYCLES_A2D"/> + <value value="25" name="A7XX_PERF_RB_2D_STARVE_CYCLES_SRC"/> + <value value="26" name="A7XX_PERF_RB_2D_STARVE_CYCLES_SP"/> + <value value="27" name="A7XX_PERF_RB_2D_STARVE_CYCLES_DST"/> + <value value="28" name="A7XX_PERF_RB_2D_VALID_PIXELS"/> + <value value="29" name="A7XX_PERF_RB_3D_PIXELS"/> + <value value="30" name="A7XX_PERF_RB_BLENDER_WORKING_CYCLES"/> + <value value="31" name="A7XX_PERF_RB_ZPROC_WORKING_CYCLES"/> + <value value="32" name="A7XX_PERF_RB_CPROC_WORKING_CYCLES"/> + <value value="33" name="A7XX_PERF_RB_SAMPLER_WORKING_CYCLES"/> + <value value="34" name="A7XX_PERF_RB_STALL_CYCLES_CCU_COLOR_READ"/> + <value value="35" name="A7XX_PERF_RB_STALL_CYCLES_CCU_COLOR_WRITE"/> + <value value="36" name="A7XX_PERF_RB_STALL_CYCLES_CCU_DEPTH_READ"/> + <value value="37" name="A7XX_PERF_RB_STALL_CYCLES_CCU_DEPTH_WRITE"/> + <value value="38" name="A7XX_PERF_RB_STALL_CYCLES_VPC"/> + <value value="39" name="A7XX_PERF_RB_2D_INPUT_TRANS"/> + <value value="40" name="A7XX_PERF_RB_2D_OUTPUT_RB_DST_TRANS"/> + <value value="41" name="A7XX_PERF_RB_2D_OUTPUT_RB_SRC_TRANS"/> + <value value="42" name="A7XX_PERF_RB_BLENDED_FP32_COMPONENTS"/> + <value value="43" name="A7XX_PERF_RB_COLOR_PIX_TILES"/> + <value value="44" name="A7XX_PERF_RB_STALL_CYCLES_CCU"/> + <value value="45" name="A7XX_PERF_RB_EARLY_Z_ARB3_GRANT"/> + <value value="46" name="A7XX_PERF_RB_LATE_Z_ARB3_GRANT"/> + <value value="47" name="A7XX_PERF_RB_EARLY_Z_SKIP_GRANT"/> + <value value="48" name="A7XX_PERF_RB_VRS_1x1_QUADS"/> + <value value="49" name="A7XX_PERF_RB_VRS_2x1_QUADS"/> + <value value="50" name="A7XX_PERF_RB_VRS_1x2_QUADS"/> + <value value="51" name="A7XX_PERF_RB_VRS_2x2_QUADS"/> + <value value="52" name="A7XX_PERF_RB_VRS_4x2_QUADS"/> + <value value="53" name="A7XX_PERF_RB_VRS_4x4_QUADS"/> +</enum> + +<enum name="a7xx_vsc_perfcounter_select"> + <value value="0" name="A7XX_PERF_VSC_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_VSC_WORKING_CYCLES"/> + <value value="2" name="A7XX_PERF_VSC_STALL_CYCLES_UCHE"/> + <value value="3" name="A7XX_PERF_VSC_EOT_NUM"/> + <value value="4" name="A7XX_PERF_VSC_INPUT_TILES"/> +</enum> + +<enum name="a7xx_ccu_perfcounter_select"> + <value value="0" name="A7XX_PERF_CCU_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_CCU_STALL_CYCLES_RB_DEPTH_RETURN"/> + <value value="2" name="A7XX_PERF_CCU_STALL_CYCLES_RB_COLOR_RETURN"/> + <value value="3" name="A7XX_PERF_CCU_DEPTH_BLOCKS"/> + <value value="4" name="A7XX_PERF_CCU_COLOR_BLOCKS"/> + <value value="5" name="A7XX_PERF_CCU_DEPTH_BLOCK_HIT"/> + <value value="6" name="A7XX_PERF_CCU_COLOR_BLOCK_HIT"/> + <value value="7" name="A7XX_PERF_CCU_PARTIAL_BLOCK_READ"/> + <value value="8" name="A7XX_PERF_CCU_GMEM_READ"/> + <value value="9" name="A7XX_PERF_CCU_GMEM_WRITE"/> + <value value="10" name="A7XX_PERF_CCU_2D_RD_REQ"/> + <value value="11" name="A7XX_PERF_CCU_2D_WR_REQ"/> + <value value="12" name="A7XX_PERF_CCU_UBWC_COLOR_BLOCKS_CONCURRENT"/> + <value value="13" name="A7XX_PERF_CCU_UBWC_DEPTH_BLOCKS_CONCURRENT"/> + <value value="14" name="A7XX_PERF_CCU_COLOR_RESOLVE_DROPPED"/> + <value value="15" name="A7XX_PERF_CCU_DEPTH_RESOLVE_DROPPED"/> + <value value="16" name="A7XX_PERF_CCU_COLOR_RENDER_CONCURRENT"/> + <value value="17" name="A7XX_PERF_CCU_DEPTH_RENDER_CONCURRENT"/> + <value value="18" name="A7XX_PERF_CCU_COLOR_RESOLVE_AFTER_RENDER"/> + <value value="19" name="A7XX_PERF_CCU_DEPTH_RESOLVE_AFTER_RENDER"/> + <value value="20" name="A7XX_PERF_CCU_GMEM_EXTRA_DEPTH_READ"/> + <value value="21" name="A7XX_PERF_CCU_GMEM_COLOR_READ_4AA"/> + <value value="22" name="A7XX_PERF_CCU_GMEM_COLOR_READ_4AA_FULL"/> +</enum> + +<enum name="a7xx_lrz_perfcounter_select"> + <value value="0" name="A7XX_PERF_LRZ_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_LRZ_STARVE_CYCLES_RAS"/> + <value value="2" name="A7XX_PERF_LRZ_STALL_CYCLES_RB"/> + <value value="3" name="A7XX_PERF_LRZ_STALL_CYCLES_VSC"/> + <value value="4" name="A7XX_PERF_LRZ_STALL_CYCLES_VPC"/> + <value value="5" name="A7XX_PERF_LRZ_STALL_CYCLES_FLAG_PREFETCH"/> + <value value="6" name="A7XX_PERF_LRZ_STALL_CYCLES_UCHE"/> + <value value="7" name="A7XX_PERF_LRZ_LRZ_READ"/> + <value value="8" name="A7XX_PERF_LRZ_LRZ_WRITE"/> + <value value="9" name="A7XX_PERF_LRZ_READ_LATENCY"/> + <value value="10" name="A7XX_PERF_LRZ_MERGE_CACHE_UPDATING"/> + <value value="11" name="A7XX_PERF_LRZ_PRIM_KILLED_BY_MASKGEN"/> + <value value="12" name="A7XX_PERF_LRZ_PRIM_KILLED_BY_LRZ"/> + <value value="13" name="A7XX_PERF_LRZ_VISIBLE_PRIM_AFTER_LRZ"/> + <value value="14" name="A7XX_PERF_LRZ_FULL_8X8_TILES"/> + <value value="15" name="A7XX_PERF_LRZ_PARTIAL_8X8_TILES"/> + <value value="16" name="A7XX_PERF_LRZ_TILE_KILLED"/> + <value value="17" name="A7XX_PERF_LRZ_TOTAL_PIXEL"/> + <value value="18" name="A7XX_PERF_LRZ_VISIBLE_PIXEL_AFTER_LRZ"/> + <value value="19" name="A7XX_PERF_LRZ_FEEDBACK_ACCEPT"/> + <value value="20" name="A7XX_PERF_LRZ_FEEDBACK_DISCARD"/> + <value value="21" name="A7XX_PERF_LRZ_FEEDBACK_STALL"/> + <value value="22" name="A7XX_PERF_LRZ_STALL_CYCLES_RB_ZPLANE"/> + <value value="23" name="A7XX_PERF_LRZ_STALL_CYCLES_RB_BPLANE"/> + <value value="24" name="A7XX_PERF_LRZ_RAS_MASK_TRANS"/> + <value value="25" name="A7XX_PERF_LRZ_STALL_CYCLES_MVC"/> + <value value="26" name="A7XX_PERF_LRZ_TILE_KILLED_BY_IMAGE_VRS"/> + <value value="27" name="A7XX_PERF_LRZ_TILE_KILLED_BY_Z"/> +</enum> + +<enum name="a7xx_cmp_perfcounter_select"> + <value value="0" name="A7XX_PERF_CMPDECMP_STALL_CYCLES_ARB"/> + <value value="1" name="A7XX_PERF_CMPDECMP_VBIF_LATENCY_CYCLES"/> + <value value="2" name="A7XX_PERF_CMPDECMP_VBIF_LATENCY_SAMPLES"/> + <value value="3" name="A7XX_PERF_CMPDECMP_VBIF_READ_DATA_CCU"/> + <value value="4" name="A7XX_PERF_CMPDECMP_VBIF_WRITE_DATA_CCU"/> + <value value="5" name="A7XX_PERF_CMPDECMP_VBIF_READ_REQUEST"/> + <value value="6" name="A7XX_PERF_CMPDECMP_VBIF_WRITE_REQUEST"/> + <value value="7" name="A7XX_PERF_CMPDECMP_VBIF_READ_DATA"/> + <value value="8" name="A7XX_PERF_CMPDECMP_VBIF_WRITE_DATA"/> + <value value="9" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG1_COUNT"/> + <value value="10" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG2_COUNT"/> + <value value="11" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG3_COUNT"/> + <value value="12" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG4_COUNT"/> + <value value="13" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG5_COUNT"/> + <value value="14" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG6_COUNT"/> + <value value="15" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG8_COUNT"/> + <value value="16" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG1_COUNT"/> + <value value="17" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG2_COUNT"/> + <value value="18" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG3_COUNT"/> + <value value="19" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG4_COUNT"/> + <value value="20" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG5_COUNT"/> + <value value="21" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG6_COUNT"/> + <value value="22" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG8_COUNT"/> + <value value="23" name="A7XX_PERF_CMPDECMP_VBIF_READ_DATA_UCHE_CH0"/> + <value value="24" name="A7XX_PERF_CMPDECMP_VBIF_READ_DATA_UCHE_CH1"/> + <value value="25" name="A7XX_PERF_CMPDECMP_VBIF_WRITE_DATA_UCHE"/> + <value value="26" name="A7XX_PERF_CMPDECMP_DEPTH_WRITE_FLAG0_COUNT"/> + <value value="27" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAG0_COUNT"/> + <value value="28" name="A7XX_PERF_CMPDECMP_COLOR_WRITE_FLAGALPHA_COUNT"/> + <value value="29" name="A7XX_PERF_CMPDECMP_RESOLVE_EVENTS"/> + <value value="30" name="A7XX_PERF_CMPDECMP_CONCURRENT_RESOLVE_EVENTS"/> + <value value="31" name="A7XX_PERF_CMPDECMP_DROPPED_CLEAR_EVENTS"/> + <value value="32" name="A7XX_PERF_CMPDECMP_ST_BLOCKS_CONCURRENT"/> + <value value="33" name="A7XX_PERF_CMPDECMP_LRZ_ST_BLOCKS_CONCURRENT"/> + <value value="34" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG0_COUNT"/> + <value value="35" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG1_COUNT"/> + <value value="36" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG2_COUNT"/> + <value value="37" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG3_COUNT"/> + <value value="38" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG4_COUNT"/> + <value value="39" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG5_COUNT"/> + <value value="40" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG6_COUNT"/> + <value value="41" name="A7XX_PERF_CMPDECMP_DEPTH_READ_FLAG8_COUNT"/> + <value value="42" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG0_COUNT"/> + <value value="43" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG1_COUNT"/> + <value value="44" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG2_COUNT"/> + <value value="45" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG3_COUNT"/> + <value value="46" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG4_COUNT"/> + <value value="47" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG5_COUNT"/> + <value value="48" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG6_COUNT"/> + <value value="49" name="A7XX_PERF_CMPDECMP_COLOR_READ_FLAG8_COUNT"/> +</enum> + +<enum name="a7xx_gbif_perfcounter_select"> + <value value="0" name="A7XX_PERF_GBIF_RESERVED_0"/> + <value value="1" name="A7XX_PERF_GBIF_RESERVED_1"/> + <value value="2" name="A7XX_PERF_GBIF_RESERVED_2"/> + <value value="3" name="A7XX_PERF_GBIF_RESERVED_3"/> + <value value="4" name="A7XX_PERF_GBIF_RESERVED_4"/> + <value value="5" name="A7XX_PERF_GBIF_RESERVED_5"/> + <value value="6" name="A7XX_PERF_GBIF_RESERVED_6"/> + <value value="7" name="A7XX_PERF_GBIF_RESERVED_7"/> + <value value="8" name="A7XX_PERF_GBIF_RESERVED_8"/> + <value value="9" name="A7XX_PERF_GBIF_RESERVED_9"/> + <value value="10" name="A7XX_PERF_GBIF_AXI0_READ_REQUESTS_TOTAL"/> + <value value="11" name="A7XX_PERF_GBIF_AXI1_READ_REQUESTS_TOTAL"/> + <value value="12" name="A7XX_PERF_GBIF_RESERVED_12"/> + <value value="13" name="A7XX_PERF_GBIF_RESERVED_13"/> + <value value="14" name="A7XX_PERF_GBIF_RESERVED_14"/> + <value value="15" name="A7XX_PERF_GBIF_RESERVED_15"/> + <value value="16" name="A7XX_PERF_GBIF_RESERVED_16"/> + <value value="17" name="A7XX_PERF_GBIF_RESERVED_17"/> + <value value="18" name="A7XX_PERF_GBIF_RESERVED_18"/> + <value value="19" name="A7XX_PERF_GBIF_RESERVED_19"/> + <value value="20" name="A7XX_PERF_GBIF_RESERVED_20"/> + <value value="21" name="A7XX_PERF_GBIF_RESERVED_21"/> + <value value="22" name="A7XX_PERF_GBIF_AXI0_WRITE_REQUESTS_TOTAL"/> + <value value="23" name="A7XX_PERF_GBIF_AXI1_WRITE_REQUESTS_TOTAL"/> + <value value="24" name="A7XX_PERF_GBIF_RESERVED_24"/> + <value value="25" name="A7XX_PERF_GBIF_RESERVED_25"/> + <value value="26" name="A7XX_PERF_GBIF_RESERVED_26"/> + <value value="27" name="A7XX_PERF_GBIF_RESERVED_27"/> + <value value="28" name="A7XX_PERF_GBIF_RESERVED_28"/> + <value value="29" name="A7XX_PERF_GBIF_RESERVED_29"/> + <value value="30" name="A7XX_PERF_GBIF_RESERVED_30"/> + <value value="31" name="A7XX_PERF_GBIF_RESERVED_31"/> + <value value="32" name="A7XX_PERF_GBIF_RESERVED_32"/> + <value value="33" name="A7XX_PERF_GBIF_RESERVED_33"/> + <value value="34" name="A7XX_PERF_GBIF_AXI0_READ_DATA_BEATS_TOTAL"/> + <value value="35" name="A7XX_PERF_GBIF_AXI1_READ_DATA_BEATS_TOTAL"/> + <value value="36" name="A7XX_PERF_GBIF_RESERVED_36"/> + <value value="37" name="A7XX_PERF_GBIF_RESERVED_37"/> + <value value="38" name="A7XX_PERF_GBIF_RESERVED_38"/> + <value value="39" name="A7XX_PERF_GBIF_RESERVED_39"/> + <value value="40" name="A7XX_PERF_GBIF_RESERVED_40"/> + <value value="41" name="A7XX_PERF_GBIF_RESERVED_41"/> + <value value="42" name="A7XX_PERF_GBIF_RESERVED_42"/> + <value value="43" name="A7XX_PERF_GBIF_RESERVED_43"/> + <value value="44" name="A7XX_PERF_GBIF_RESERVED_44"/> + <value value="45" name="A7XX_PERF_GBIF_RESERVED_45"/> + <value value="46" name="A7XX_PERF_GBIF_AXI0_WRITE_DATA_BEATS_TOTAL"/> + <value value="47" name="A7XX_PERF_GBIF_AXI1_WRITE_DATA_BEATS_TOTAL"/> + <value value="48" name="A7XX_PERF_GBIF_RESERVED_48"/> + <value value="49" name="A7XX_PERF_GBIF_RESERVED_49"/> + <value value="50" name="A7XX_PERF_GBIF_RESERVED_50"/> + <value value="51" name="A7XX_PERF_GBIF_RESERVED_51"/> + <value value="52" name="A7XX_PERF_GBIF_RESERVED_52"/> + <value value="53" name="A7XX_PERF_GBIF_RESERVED_53"/> + <value value="54" name="A7XX_PERF_GBIF_RESERVED_54"/> + <value value="55" name="A7XX_PERF_GBIF_RESERVED_55"/> + <value value="56" name="A7XX_PERF_GBIF_RESERVED_56"/> + <value value="57" name="A7XX_PERF_GBIF_RESERVED_57"/> + <value value="58" name="A7XX_PERF_GBIF_RESERVED_58"/> + <value value="59" name="A7XX_PERF_GBIF_RESERVED_59"/> + <value value="60" name="A7XX_PERF_GBIF_RESERVED_60"/> + <value value="61" name="A7XX_PERF_GBIF_RESERVED_61"/> + <value value="62" name="A7XX_PERF_GBIF_RESERVED_62"/> + <value value="63" name="A7XX_PERF_GBIF_RESERVED_63"/> + <value value="64" name="A7XX_PERF_GBIF_RESERVED_64"/> + <value value="65" name="A7XX_PERF_GBIF_RESERVED_65"/> + <value value="66" name="A7XX_PERF_GBIF_RESERVED_66"/> + <value value="67" name="A7XX_PERF_GBIF_RESERVED_67"/> + <value value="68" name="A7XX_PERF_GBIF_CYCLES_CH0_HELD_OFF_RD_ALL"/> + <value value="69" name="A7XX_PERF_GBIF_CYCLES_CH1_HELD_OFF_RD_ALL"/> + <value value="70" name="A7XX_PERF_GBIF_CYCLES_CH0_HELD_OFF_WR_ALL"/> + <value value="71" name="A7XX_PERF_GBIF_CYCLES_CH1_HELD_OFF_WR_ALL"/> + <value value="72" name="A7XX_PERF_GBIF_AXI_CH0_REQUEST_HELD_OFF"/> + <value value="73" name="A7XX_PERF_GBIF_AXI_CH1_REQUEST_HELD_OFF"/> + <value value="74" name="A7XX_PERF_GBIF_AXI_REQUEST_HELD_OFF"/> + <value value="75" name="A7XX_PERF_GBIF_AXI_CH0_WRITE_DATA_HELD_OFF"/> + <value value="76" name="A7XX_PERF_GBIF_AXI_CH1_WRITE_DATA_HELD_OFF"/> + <value value="77" name="A7XX_PERF_GBIF_AXI_ALL_WRITE_DATA_HELD_OFF"/> + <value value="78" name="A7XX_PERF_GBIF_AXI_ALL_READ_BEATS"/> + <value value="79" name="A7XX_PERF_GBIF_AXI_ALL_WRITE_BEATS"/> + <value value="80" name="A7XX_PERF_GBIF_AXI_ALL_BEATS"/> +</enum> + +<enum name="a7xx_ufc_perfcounter_select"> + <value value="0" name="A7XX_PERF_UFC_BUSY_CYCLES"/> + <value value="1" name="A7XX_PERF_UFC_READ_DATA_VBIF"/> + <value value="2" name="A7XX_PERF_UFC_WRITE_DATA_VBIF"/> + <value value="3" name="A7XX_PERF_UFC_READ_REQUEST_VBIF"/> + <value value="4" name="A7XX_PERF_UFC_WRITE_REQUEST_VBIF"/> + <value value="5" name="A7XX_PERF_UFC_LRZ_FILTER_HIT"/> + <value value="6" name="A7XX_PERF_UFC_LRZ_FILTER_MISS"/> + <value value="7" name="A7XX_PERF_UFC_CRE_FILTER_HIT"/> + <value value="8" name="A7XX_PERF_UFC_CRE_FILTER_MISS"/> + <value value="9" name="A7XX_PERF_UFC_SP_FILTER_HIT"/> + <value value="10" name="A7XX_PERF_UFC_SP_FILTER_MISS"/> + <value value="11" name="A7XX_PERF_UFC_SP_REQUESTS"/> + <value value="12" name="A7XX_PERF_UFC_TP_FILTER_HIT"/> + <value value="13" name="A7XX_PERF_UFC_TP_FILTER_MISS"/> + <value value="14" name="A7XX_PERF_UFC_TP_REQUESTS"/> + <value value="15" name="A7XX_PERF_UFC_MAIN_HIT_LRZ_PREFETCH"/> + <value value="16" name="A7XX_PERF_UFC_MAIN_HIT_CRE_PREFETCH"/> + <value value="17" name="A7XX_PERF_UFC_MAIN_HIT_SP_PREFETCH"/> + <value value="18" name="A7XX_PERF_UFC_MAIN_HIT_TP_PREFETCH"/> + <value value="19" name="A7XX_PERF_UFC_MAIN_HIT_UBWC_READ"/> + <value value="20" name="A7XX_PERF_UFC_MAIN_HIT_UBWC_WRITE"/> + <value value="21" name="A7XX_PERF_UFC_MAIN_MISS_LRZ_PREFETCH"/> + <value value="22" name="A7XX_PERF_UFC_MAIN_MISS_CRE_PREFETCH"/> + <value value="23" name="A7XX_PERF_UFC_MAIN_MISS_SP_PREFETCH"/> + <value value="24" name="A7XX_PERF_UFC_MAIN_MISS_TP_PREFETCH"/> + <value value="25" name="A7XX_PERF_UFC_MAIN_MISS_UBWC_READ"/> + <value value="26" name="A7XX_PERF_UFC_MAIN_MISS_UBWC_WRITE"/> + <value value="27" name="A7XX_PERF_UFC_UBWC_READ_UFC_TRANS"/> + <value value="28" name="A7XX_PERF_UFC_UBWC_WRITE_UFC_TRANS"/> + <value value="29" name="A7XX_PERF_UFC_STALL_CYCLES_GBIF_CMD"/> + <value value="30" name="A7XX_PERF_UFC_STALL_CYCLES_GBIF_RDATA"/> + <value value="31" name="A7XX_PERF_UFC_STALL_CYCLES_GBIF_WDATA"/> + <value value="32" name="A7XX_PERF_UFC_STALL_CYCLES_UBWC_WR_FLAG"/> + <value value="33" name="A7XX_PERF_UFC_STALL_CYCLES_UBWC_FLAG_RTN"/> + <value value="34" name="A7XX_PERF_UFC_STALL_CYCLES_UBWC_EVENT"/> + <value value="35" name="A7XX_PERF_UFC_LRZ_PREFETCH_STALLED_CYCLES"/> + <value value="36" name="A7XX_PERF_UFC_CRE_PREFETCH_STALLED_CYCLES"/> + <value value="37" name="A7XX_PERF_UFC_SPTP_PREFETCH_STALLED_CYCLES"/> + <value value="38" name="A7XX_PERF_UFC_UBWC_RD_STALLED_CYCLES"/> + <value value="39" name="A7XX_PERF_UFC_UBWC_WR_STALLED_CYCLES"/> + <value value="40" name="A7XX_PERF_UFC_PREFETCH_STALLED_CYCLES"/> + <value value="41" name="A7XX_PERF_UFC_EVICTION_STALLED_CYCLES"/> + <value value="42" name="A7XX_PERF_UFC_LOCK_STALLED_CYCLES"/> + <value value="43" name="A7XX_PERF_UFC_MISS_LATENCY_CYCLES"/> + <value value="44" name="A7XX_PERF_UFC_MISS_LATENCY_SAMPLES"/> + <value value="45" name="A7XX_PERF_UFC_UBWC_REQ_STALLED_CYCLES"/> + <value value="46" name="A7XX_PERF_UFC_TP_HINT_TAG_MISS"/> + <value value="47" name="A7XX_PERF_UFC_TP_HINT_TAG_HIT_RDY"/> + <value value="48" name="A7XX_PERF_UFC_TP_HINT_TAG_HIT_NRDY"/> + <value value="49" name="A7XX_PERF_UFC_TP_HINT_IS_FCLEAR"/> + <value value="50" name="A7XX_PERF_UFC_TP_HINT_IS_ALPHA0"/> + <value value="51" name="A7XX_PERF_UFC_SP_L1_FILTER_HIT"/> + <value value="52" name="A7XX_PERF_UFC_SP_L1_FILTER_MISS"/> + <value value="53" name="A7XX_PERF_UFC_SP_L1_FILTER_REQUESTS"/> + <value value="54" name="A7XX_PERF_UFC_TP_L1_TAG_HIT_RDY"/> + <value value="55" name="A7XX_PERF_UFC_TP_L1_TAG_HIT_NRDY"/> + <value value="56" name="A7XX_PERF_UFC_TP_L1_TAG_MISS"/> + <value value="57" name="A7XX_PERF_UFC_TP_L1_FILTER_REQUESTS"/> +</enum> + +</database> diff --git a/drivers/gpu/drm/msm/registers/adreno/a8xx_descriptors.xml b/drivers/gpu/drm/msm/registers/adreno/a8xx_descriptors.xml new file mode 100644 index 000000000000..edcbdb3b6921 --- /dev/null +++ b/drivers/gpu/drm/msm/registers/adreno/a8xx_descriptors.xml @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?> +<database xmlns="http://nouveau.freedesktop.org/" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> +<import file="freedreno_copyright.xml"/> +<import file="adreno/adreno_common.xml"/> +<import file="adreno/adreno_pm4.xml"/> +<import file="adreno/a6xx_enums.xml"/> +<import file="adreno/a8xx_enums.xml"/> + +<domain name="A8XX_TEX_SAMP" width="32"> + <doc>Texture sampler dwords</doc> + <reg32 offset="0" name="0"> + <bitfield name="MIPFILTER_LINEAR_NEAR" pos="0" type="boolean"/> + <bitfield name="MIPMAPING_DIS" pos="1" type="boolean"/> + <bitfield name="XY_MAG" low="2" high="3" type="a6xx_tex_filter"/> + <bitfield name="XY_MIN" low="4" high="5" type="a6xx_tex_filter"/> + <bitfield name="WRAP_S" low="6" high="8" type="a6xx_tex_clamp"/> + <bitfield name="WRAP_T" low="9" high="11" type="a6xx_tex_clamp"/> + <bitfield name="WRAP_R" low="12" high="14" type="a6xx_tex_clamp"/> + <bitfield name="MSAA_BOX_FILTERING" pos="15" type="boolean"/> + <bitfield name="LOD_BIAS" low="16" high="28" type="fixed" radix="8"/> + <bitfield name="ANISO" low="29" high="31" type="a6xx_tex_aniso"/> + </reg32> + <reg32 offset="1" name="1"> + <bitfield name="MAX_LOD" low="0" high="11" type="ufixed" radix="8"/> + <bitfield name="MIN_LOD" low="12" high="23" type="ufixed" radix="8"/> + <bitfield name="REDUCTION_MODE" low="24" high="25" type="a6xx_reduction_mode"/> + <bitfield name="COMPARE_FUNC" low="26" high="28" type="adreno_compare_func"/> + <bitfield name="CHROMA_LINEAR" pos="29" type="boolean"/> + <bitfield name="CUBEMAPSEAMLESSFILTOFF" pos="30" type="boolean"/> + <bitfield name="UNNORM_COORDS" pos="31" type="boolean"/> + </reg32> + <reg32 offset="2" name="2"> + <bitfield name="FASTBORDERCOLOREN" pos="0" type="boolean"/> + <bitfield name="FASTBORDERCOLOR" low="1" high="2" type="a6xx_fast_border_color"/> + <bitfield name="BCOLOR" low="7" high="31"/> + </reg32> + <reg32 offset="3" name="3"/> +</domain> + +<domain name="A8XX_TEX_MEMOBJ" width="32" varset="chip"> + <doc>Texture memobj dwords</doc> + <reg32 offset="0" name="0"> + <bitfield name="BASE_LO" low="6" high="31" shr="6"/> + </reg32> + <reg32 offset="1" name="1"> + <bitfield name="BASE_HI" low="0" high="16"/> + <bitfield name="TYPE" low="17" high="19" type="a6xx_tex_type"/> + <bitfield name="DEPTH" low="20" high="31" type="uint"/> + </reg32> + <reg32 offset="2" name="2"> + <bitfield name="WIDTH" low="0" high="14" type="uint"/> + <bitfield name="HEIGHT" low="15" high="29" type="uint"/> + <bitfield name="SAMPLES" low="30" high="31" type="a3xx_msaa_samples"/> + </reg32> + <reg32 offset="3" name="3"> + <bitfield name="FMT" low="0" high="7" type="a6xx_format"/> + <bitfield name="SWAP" low="8" high="9" type="a3xx_color_swap"/> + <bitfield name="SWIZ_X" low="10" high="12" type="a8xx_tex_swiz"/> + <bitfield name="SWIZ_Y" low="13" high="15" type="a8xx_tex_swiz"/> + <bitfield name="SWIZ_Z" low="16" high="18" type="a8xx_tex_swiz"/> + <bitfield name="SWIZ_W" low="19" high="21" type="a8xx_tex_swiz"/> + </reg32> + <reg32 offset="4" name="4"> + <bitfield name="TILE_MODE" low="0" high="1" type="a6xx_tile_mode"/> + <bitfield name="FLAG" pos="2" type="boolean"/> + <bitfield name="PRT_EN" pos="3" type="boolean"/> + <bitfield name="TILE_ALL" pos="4" type="boolean"/> + <bitfield name="SRGB" pos="5" type="boolean"/> + <bitfield name="FLAG_LO" low="6" high="31" shr="6"/> + <!-- For multiplanar: --> + <bitfield name="BASE_U_LO" low="6" high="31" shr="6"/> + </reg32> + <reg32 offset="5" name="5"> + <bitfield name="FLAG_HI" low="0" high="16"/> + <!-- For multiplanar: --> + <bitfield name="BASE_U_HI" low="0" high="16"/> + <bitfield name="FLAG_BUFFER_PITCH" low="17" high="24" shr="6" type="uint"/> + <bitfield name="ALL_SAMPLES_CENTER" pos="29" type="boolean"/> + <bitfield name="MUTABLEEN" pos="31" type="boolean"/> + </reg32> + <reg32 offset="6" name="6"> + <bitfield name="TEX_LINE_OFFSET" low="0" high="23" type="uint"/> <!-- PITCH --> + <bitfield name="MIN_LINE_OFFSET" low="24" high="27" type="uint"/> <!-- PITCHALIGN --> + <bitfield name="MIPLVLS" low="28" high="31" type="uint"/> + </reg32> + <reg32 offset="7" name="7"> + <bitfield name="ARRAY_SLICE_OFFSET" low="0" high="22" shr="12" type="uint"/> <!-- ARRAY_PITCH --> + <bitfield name="ASO_UNIT" pos="23"/> <!-- 4KB or 32B ? --> + <bitfield name="MIN_ARRAY_SLIZE_OFFSET" low="24" high="27" shr="12"/> <!-- MIN_LAYERSZ --> + <bitfield name="GMEM_TILING_FALLBACK_EN" pos="28" type="boolean"/> + <bitfield name="CORNER_BASED_EN" pos="30" type="boolean"/> + <bitfield name="GMEM_FULL_SURF" pos="31" type="boolean"/> + <!-- For multiplanar. This overlaps other single-planar fields: --> + <bitfield name="UV_OFFSET_H" low="24" high="25" type="ufixed" radix="2"/> <!-- CHROMA_MIDPOINT_X --> + <bitfield name="UV_OFFSET_V" low="26" high="27" type="ufixed" radix="2"/> <!-- CHROMA_MIDPOINT_Y --> + </reg32> + <reg32 offset="8" name="8"> + <bitfield name="FLAG_ARRAY_PITCH" low="0" high="14" shr="12" type="uint"/> <!-- FLAG_BUFFER_ARRAY_PITCH --> + <!-- log2 size of the first level, required for mipmapping --> + <bitfield name="FLAG_BUFFER_LOGW" low="24" high="27" type="uint"/> + <bitfield name="FLAG_BUFFER_LOGH" low="28" high="31" type="uint"/> + <!-- For multiplanar. This overlaps other single-planar fields: --> + <bitfield name="BASE_V_LO" low="6" high="31" shr="6"/> + </reg32> + <reg32 offset="9" name="9"> + <bitfield name="MIN_LOD_CLAMP" low="19" high="30" type="ufixed" radix="8"/> + <!-- For multiplanar, this overlaps other fields: --> + <bitfield name="BASE_V_HI" low="0" high="16"/> + <bitfield name="UV_PITCH" low="17" high="26"/> <!-- PLANE_PITCH --> + </reg32> + <reg32 offset="10" name="10"/> + <reg32 offset="11" name="11"/> + <reg32 offset="12" name="12"/> + <reg32 offset="13" name="13"/> + <reg32 offset="14" name="14"/> + <reg32 offset="15" name="15"/> +</domain> + +</database> diff --git a/drivers/gpu/drm/msm/registers/adreno/a8xx_enums.xml b/drivers/gpu/drm/msm/registers/adreno/a8xx_enums.xml new file mode 100644 index 000000000000..c842db8c78d6 --- /dev/null +++ b/drivers/gpu/drm/msm/registers/adreno/a8xx_enums.xml @@ -0,0 +1,299 @@ +<?xml version="1.0" encoding="UTF-8"?> +<database xmlns="http://nouveau.freedesktop.org/" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> +<import file="freedreno_copyright.xml"/> +<import file="adreno/adreno_common.xml"/> +<import file="adreno/adreno_pm4.xml"/> + +<enum name="a8xx_statetype_id"> + <value value="0" name="A8XX_TP0_NCTX_REG"/> + <value value="1" name="A8XX_TP0_CTX0_3D_CVS_REG"/> + <value value="2" name="A8XX_TP0_CTX0_3D_CPS_REG"/> + <value value="3" name="A8XX_TP0_CTX1_3D_CVS_REG"/> + <value value="4" name="A8XX_TP0_CTX1_3D_CPS_REG"/> + <value value="5" name="A8XX_TP0_CTX2_3D_CPS_REG"/> + <value value="6" name="A8XX_TP0_CTX3_3D_CPS_REG"/> + <value value="9" name="A8XX_TP0_TMO_DATA"/> + <value value="10" name="A8XX_TP0_SMO_DATA"/> + <value value="11" name="A8XX_TP0_MIPMAP_BASE_DATA"/> + <value value="12" name="A8XX_TP_3D_CVS_REG"/> + <value value="13" name="A8XX_TP_3D_CPS_REG"/> + <value value="16" name="A8XX_SP_3D_CVS_REG"/> + <value value="17" name="A8XX_SP_3D_CPS_REG"/> + <value value="22" name="A8XX_SP_LB_DATA_RAM"/> + <value value="23" name="A8XX_SP_INST_DATA_RAM"/> + <value value="24" name="A8XX_SP_STH"/> + <value value="25" name="A8XX_SP_EVQ"/> + <value value="26" name="A8XX_SP_CONSMNG"/> + <value value="30" name="A8XX_HLSQ_INST_DATA_RAM"/> + <value value="31" name="A8XX_SP_INST_DATA_3"/> + <value value="32" name="A8XX_SP_NCTX_REG"/> + <value value="33" name="A8XX_SP_CTX0_3D_CVS_REG"/> + <value value="34" name="A8XX_SP_CTX0_3D_CPS_REG"/> + <value value="35" name="A8XX_SP_CTX1_3D_CVS_REG"/> + <value value="36" name="A8XX_SP_CTX1_3D_CPS_REG"/> + <value value="37" name="A8XX_SP_CTX2_3D_CPS_REG"/> + <value value="38" name="A8XX_SP_CTX3_3D_CPS_REG"/> + <value value="39" name="A8XX_SP_INST_DATA"/> + <value value="40" name="A8XX_SP_INST_DATA_1"/> + <value value="41" name="A8XX_SP_LB_0_DATA"/> + <value value="42" name="A8XX_SP_LB_1_DATA"/> + <value value="43" name="A8XX_SP_LB_2_DATA"/> + <value value="44" name="A8XX_SP_LB_3_DATA"/> + <value value="45" name="A8XX_SP_LB_4_DATA"/> + <value value="46" name="A8XX_SP_LB_5_DATA"/> + <value value="47" name="A8XX_SP_LB_6_DATA"/> + <value value="48" name="A8XX_SP_LB_7_DATA"/> + <value value="49" name="A8XX_SP_CB_RAM"/> + <value value="50" name="A8XX_SP_LB_13_DATA"/> + <value value="51" name="A8XX_SP_LB_14_DATA"/> + <value value="52" name="A8XX_SP_INST_TAG"/> + <value value="53" name="A8XX_SP_INST_DATA_2"/> + <value value="54" name="A8XX_SP_TMO_TAG"/> + <value value="55" name="A8XX_SP_SMO_TAG"/> + <value value="56" name="A8XX_SP_STATE_DATA"/> + <value value="57" name="A8XX_SP_HWAVE_RAM"/> + <value value="58" name="A8XX_SP_L0_INST_BUF"/> + <value value="59" name="A8XX_SP_LB_8_DATA"/> + <value value="60" name="A8XX_SP_LB_9_DATA"/> + <value value="61" name="A8XX_SP_LB_10_DATA"/> + <value value="62" name="A8XX_SP_LB_11_DATA"/> + <value value="63" name="A8XX_SP_LB_12_DATA"/> + <value value="64" name="A8XX_HLSQ_DATAPATH_DSTR_META"/> + <value value="65" name="A8XX_HLSQ_DESC_REMAP_META"/> + <value value="66" name="A8XX_HLSQ_SLICE_TOP_META"/> + <value value="67" name="A8XX_HLSQ_L2STC_TAG_RAM"/> + <value value="68" name="A8XX_HLSQ_L2STC_INFO_CMD"/> + <value value="69" name="A8XX_HLSQ_CVS_BE_CTXT_BUF_RAM_TAG"/> + <value value="70" name="A8XX_HLSQ_CPS_BE_CTXT_BUF_RAM_TAG"/> + <value value="71" name="A8XX_HLSQ_GFX_CVS_BE_CTXT_BUF_RAM"/> + <value value="72" name="A8XX_HLSQ_GFX_CPS_BE_CTXT_BUF_RAM"/> + <value value="73" name="A8XX_HLSQ_CHUNK_CVS_RAM"/> + <value value="74" name="A8XX_HLSQ_CHUNK_CPS_RAM"/> + <value value="75" name="A8XX_HLSQ_CHUNK_CVS_RAM_TAG"/> + <value value="76" name="A8XX_HLSQ_CHUNK_CPS_RAM_TAG"/> + <value value="77" name="A8XX_HLSQ_ICB_CVS_CB_BASE_TAG"/> + <value value="78" name="A8XX_HLSQ_ICB_CPS_CB_BASE_TAG"/> + <value value="79" name="A8XX_HLSQ_CVS_MISC_RAM"/> + <value value="80" name="A8XX_HLSQ_CPS_MISC_RAM"/> + <value value="81" name="A8XX_HLSQ_CPS_MISC_RAM_1"/> + <value value="82" name="A8XX_HLSQ_INST_RAM"/> + <value value="83" name="A8XX_HLSQ_GFX_CVS_CONST_RAM"/> + <value value="84" name="A8XX_HLSQ_GFX_CPS_CONST_RAM"/> + <value value="85" name="A8XX_HLSQ_CVS_MISC_RAM_TAG"/> + <value value="86" name="A8XX_HLSQ_CPS_MISC_RAM_TAG"/> + <value value="87" name="A8XX_HLSQ_INST_RAM_TAG"/> + <value value="88" name="A8XX_HLSQ_GFX_CVS_CONST_RAM_TAG"/> + <value value="89" name="A8XX_HLSQ_GFX_CPS_CONST_RAM_TAG"/> + <value value="90" name="A8XX_HLSQ_GFX_LOCAL_MISC_RAM"/> + <value value="91" name="A8XX_HLSQ_GFX_LOCAL_MISC_RAM_TAG"/> + <value value="92" name="A8XX_HLSQ_INST_RAM_1"/> + <value value="93" name="A8XX_HLSQ_STPROC_META"/> + <value value="94" name="A8XX_HLSQ_SLICE_BACKEND_META"/> + <value value="95" name="A8XX_HLSQ_INST_RAM_2"/> + <value value="96" name="A8XX_HLSQ_DATAPATH_META"/> + <value value="97" name="A8XX_HLSQ_FRONTEND_META"/> + <value value="98" name="A8XX_HLSQ_INDIRECT_META"/> + <value value="99" name="A8XX_HLSQ_BACKEND_META"/> +</enum> + +<enum name="a8xx_state_location"> + <value value="0" name="A8XX_HLSQ_STATE"/> + <value value="1" name="A8XX_HLSQ_DP"/> + <value value="2" name="A8XX_SP_TOP"/> + <value value="3" name="A8XX_USPTP"/> + <value value="4" name="A8XX_HLSQ_DP_STR"/> +</enum> + +<enum name="a8xx_cluster"> + <value value="0" name="A8XX_CLUSTER_NONE"/> + <value value="1" name="A8XX_CLUSTER_FE_US"/> + <value value="2" name="A8XX_CLUSTER_FE_S"/> + <value value="3" name="A8XX_CLUSTER_SP_VS"/> + <value value="4" name="A8XX_CLUSTER_VPC_VS"/> + <value value="5" name="A8XX_CLUSTER_VPC_US"/> + <value value="6" name="A8XX_CLUSTER_GRAS"/> + <value value="7" name="A8XX_CLUSTER_SP_PS"/> + <value value="8" name="A8XX_CLUSTER_VPC_PS"/> + <value value="9" name="A8XX_CLUSTER_PS"/> +</enum> + +<enum name="a8xx_debugbus_id"> + <value value="1" name="A8XX_DEBUGBUS_GBIF_CX_GC_US_I_0"/> + <value value="2" name="A8XX_DEBUGBUS_GMU_CX_GC_US_I_0"/> + <value value="3" name="A8XX_DEBUGBUS_CX_GC_US_I_0"/> + <value value="8" name="A8XX_DEBUGBUS_GBIF_GX_GC_US_I_0"/> + <value value="9" name="A8XX_DEBUGBUS_GMU_GX_GC_US_I_0"/> + <value value="10" name="A8XX_DEBUGBUS_DBGC_GC_US_I_0"/> + <value value="11" name="A8XX_DEBUGBUS_RBBM_GC_US_I_0"/> + <value value="12" name="A8XX_DEBUGBUS_LARC_GC_US_I_0"/> + <value value="13" name="A8XX_DEBUGBUS_COM_GC_US_I_0"/> + <value value="14" name="A8XX_DEBUGBUS_HLSQ_GC_US_I_0"/> + <value value="15" name="A8XX_DEBUGBUS_CGC_GC_US_I_0"/> + <value value="20" name="A8XX_DEBUGBUS_VSC_GC_US_I_0_0"/> + <value value="21" name="A8XX_DEBUGBUS_VSC_GC_US_I_0_1"/> + <value value="24" name="A8XX_DEBUGBUS_UFC_GC_US_I_0"/> + <value value="25" name="A8XX_DEBUGBUS_UFC_GC_US_I_1"/> + <value value="40" name="A8XX_DEBUGBUS_CP_GC_US_I_0_0"/> + <value value="41" name="A8XX_DEBUGBUS_CP_GC_US_I_0_1"/> + <value value="42" name="A8XX_DEBUGBUS_CP_GC_US_I_0_2"/> + <value value="56" name="A8XX_DEBUGBUS_PC_BR_US_I_0"/> + <value value="57" name="A8XX_DEBUGBUS_PC_BV_US_I_0"/> + <value value="58" name="A8XX_DEBUGBUS_GPC_BR_US_I_0"/> + <value value="59" name="A8XX_DEBUGBUS_GPC_BV_US_I_0"/> + <value value="60" name="A8XX_DEBUGBUS_VPC_BR_US_I_0"/> + <value value="61" name="A8XX_DEBUGBUS_VPC_BV_US_I_0"/> + <value value="80" name="A8XX_DEBUGBUS_UCHE_WRAPPER_GC_US_I_0"/> + <value value="81" name="A8XX_DEBUGBUS_UCHE_GC_US_I_0"/> + <value value="82" name="A8XX_DEBUGBUS_UCHE_GC_US_I_1"/> + <value value="83" name="A8XX_DEBUGBUS_UCHE_GC_US_I_0_1"/> + <value value="84" name="A8XX_DEBUGBUS_UCHE_GC_US_I_1_1"/> + <value value="128" name="A8XX_DEBUGBUS_CP_GC_S_0_I_0"/> + <value value="129" name="A8XX_DEBUGBUS_PC_BR_S_0_I_0"/> + <value value="130" name="A8XX_DEBUGBUS_PC_BV_S_0_I_0"/> + <value value="131" name="A8XX_DEBUGBUS_TESS_GC_S_0_I_0"/> + <value value="132" name="A8XX_DEBUGBUS_TSEFE_GC_S_0_I_0"/> + <value value="133" name="A8XX_DEBUGBUS_TSEBE_GC_S_0_I_0"/> + <value value="134" name="A8XX_DEBUGBUS_RAS_GC_S_0_I_0"/> + <value value="135" name="A8XX_DEBUGBUS_LRZ_BR_S_0_I_0"/> + <value value="136" name="A8XX_DEBUGBUS_LRZ_BV_S_0_I_0"/> + <value value="137" name="A8XX_DEBUGBUS_VFDP_GC_S_0_I_0"/> + <value value="138" name="A8XX_DEBUGBUS_GPC_BR_S_0_I_0"/> + <value value="139" name="A8XX_DEBUGBUS_GPC_BV_S_0_I_0"/> + <value value="140" name="A8XX_DEBUGBUS_VPCFE_BR_S_0_I_0"/> + <value value="141" name="A8XX_DEBUGBUS_VPCFE_BV_S_0_I_0"/> + <value value="142" name="A8XX_DEBUGBUS_VPCBE_BR_S_0_I_0"/> + <value value="143" name="A8XX_DEBUGBUS_VPCBE_BV_S_0_I_0"/> + <value value="144" name="A8XX_DEBUGBUS_CCHE_GC_S_0_I_0"/> + <value value="145" name="A8XX_DEBUGBUS_DBGC_GC_S_0_I_0"/> + <value value="146" name="A8XX_DEBUGBUS_LARC_GC_S_0_I_0"/> + <value value="147" name="A8XX_DEBUGBUS_RBBM_GC_S_0_I_0"/> + <value value="148" name="A8XX_DEBUGBUS_CCRE_GC_S_0_I_0"/> + <value value="149" name="A8XX_DEBUGBUS_CGC_GC_S_0_I_0"/> + <value value="150" name="A8XX_DEBUGBUS_GMU_GC_S_0_I_0"/> + <value value="151" name="A8XX_DEBUGBUS_SLICE_GC_S_0_I_0"/> + <value value="152" name="A8XX_DEBUGBUS_HLSQ_SPTP_STAR_GC_S_0_I_0"/> + <value value="160" name="A8XX_DEBUGBUS_USP_GC_S_0_I_0"/> + <value value="161" name="A8XX_DEBUGBUS_USP_GC_S_0_I_1"/> + <value value="166" name="A8XX_DEBUGBUS_USPTP_GC_S_0_I_0"/> + <value value="167" name="A8XX_DEBUGBUS_USPTP_GC_S_0_I_1"/> + <value value="168" name="A8XX_DEBUGBUS_USPTP_GC_S_0_I_2"/> + <value value="169" name="A8XX_DEBUGBUS_USPTP_GC_S_0_I_3"/> + <value value="178" name="A8XX_DEBUGBUS_TP_GC_S_0_I_0"/> + <value value="179" name="A8XX_DEBUGBUS_TP_GC_S_0_I_1"/> + <value value="180" name="A8XX_DEBUGBUS_TP_GC_S_0_I_2"/> + <value value="181" name="A8XX_DEBUGBUS_TP_GC_S_0_I_3"/> + <value value="190" name="A8XX_DEBUGBUS_RB_GC_S_0_I_0"/> + <value value="191" name="A8XX_DEBUGBUS_RB_GC_S_0_I_1"/> + <value value="196" name="A8XX_DEBUGBUS_CCU_GC_S_0_I_0"/> + <value value="197" name="A8XX_DEBUGBUS_CCU_GC_S_0_I_1"/> + <value value="202" name="A8XX_DEBUGBUS_HLSQ_GC_S_0_I_0"/> + <value value="203" name="A8XX_DEBUGBUS_HLSQ_GC_S_0_I_1"/> + <value value="208" name="A8XX_DEBUGBUS_VFD_GC_S_0_I_0"/> + <value value="209" name="A8XX_DEBUGBUS_VFD_GC_S_0_I_1"/> + <value value="256" name="A8XX_DEBUGBUS_CP_GC_S_1_I_0"/> + <value value="257" name="A8XX_DEBUGBUS_PC_BR_S_1_I_0"/> + <value value="258" name="A8XX_DEBUGBUS_PC_BV_S_1_I_0"/> + <value value="259" name="A8XX_DEBUGBUS_TESS_GC_S_1_I_0"/> + <value value="260" name="A8XX_DEBUGBUS_TSEFE_GC_S_1_I_0"/> + <value value="261" name="A8XX_DEBUGBUS_TSEBE_GC_S_1_I_0"/> + <value value="262" name="A8XX_DEBUGBUS_RAS_GC_S_1_I_0"/> + <value value="263" name="A8XX_DEBUGBUS_LRZ_BR_S_1_I_0"/> + <value value="264" name="A8XX_DEBUGBUS_LRZ_BV_S_1_I_0"/> + <value value="265" name="A8XX_DEBUGBUS_VFDP_GC_S_1_I_0"/> + <value value="266" name="A8XX_DEBUGBUS_GPC_BR_S_1_I_0"/> + <value value="267" name="A8XX_DEBUGBUS_GPC_BV_S_1_I_0"/> + <value value="268" name="A8XX_DEBUGBUS_VPCFE_BR_S_1_I_0"/> + <value value="269" name="A8XX_DEBUGBUS_VPCFE_BV_S_1_I_0"/> + <value value="270" name="A8XX_DEBUGBUS_VPCBE_BR_S_1_I_0"/> + <value value="271" name="A8XX_DEBUGBUS_VPCBE_BV_S_1_I_0"/> + <value value="272" name="A8XX_DEBUGBUS_CCHE_GC_S_1_I_0"/> + <value value="273" name="A8XX_DEBUGBUS_DBGC_GC_S_1_I_0"/> + <value value="274" name="A8XX_DEBUGBUS_LARC_GC_S_1_I_0"/> + <value value="275" name="A8XX_DEBUGBUS_RBBM_GC_S_1_I_0"/> + <value value="276" name="A8XX_DEBUGBUS_CCRE_GC_S_1_I_0"/> + <value value="277" name="A8XX_DEBUGBUS_CGC_GC_S_1_I_0"/> + <value value="278" name="A8XX_DEBUGBUS_GMU_GC_S_1_I_0"/> + <value value="279" name="A8XX_DEBUGBUS_SLICE_GC_S_1_I_0"/> + <value value="280" name="A8XX_DEBUGBUS_HLSQ_SPTP_STAR_GC_S_1_I_0"/> + <value value="288" name="A8XX_DEBUGBUS_USP_GC_S_1_I_0"/> + <value value="289" name="A8XX_DEBUGBUS_USP_GC_S_1_I_1"/> + <value value="294" name="A8XX_DEBUGBUS_USPTP_GC_S_1_I_0"/> + <value value="295" name="A8XX_DEBUGBUS_USPTP_GC_S_1_I_1"/> + <value value="296" name="A8XX_DEBUGBUS_USPTP_GC_S_1_I_2"/> + <value value="297" name="A8XX_DEBUGBUS_USPTP_GC_S_1_I_3"/> + <value value="306" name="A8XX_DEBUGBUS_TP_GC_S_1_I_0"/> + <value value="307" name="A8XX_DEBUGBUS_TP_GC_S_1_I_1"/> + <value value="308" name="A8XX_DEBUGBUS_TP_GC_S_1_I_2"/> + <value value="309" name="A8XX_DEBUGBUS_TP_GC_S_1_I_3"/> + <value value="318" name="A8XX_DEBUGBUS_RB_GC_S_1_I_0"/> + <value value="319" name="A8XX_DEBUGBUS_RB_GC_S_1_I_1"/> + <value value="324" name="A8XX_DEBUGBUS_CCU_GC_S_1_I_0"/> + <value value="325" name="A8XX_DEBUGBUS_CCU_GC_S_1_I_1"/> + <value value="330" name="A8XX_DEBUGBUS_HLSQ_GC_S_1_I_0"/> + <value value="331" name="A8XX_DEBUGBUS_HLSQ_GC_S_1_I_1"/> + <value value="336" name="A8XX_DEBUGBUS_VFD_GC_S_1_I_0"/> + <value value="337" name="A8XX_DEBUGBUS_VFD_GC_S_1_I_1"/> + <value value="384" name="A8XX_DEBUGBUS_CP_GC_S_2_I_0"/> + <value value="385" name="A8XX_DEBUGBUS_PC_BR_S_2_I_0"/> + <value value="386" name="A8XX_DEBUGBUS_PC_BV_S_2_I_0"/> + <value value="387" name="A8XX_DEBUGBUS_TESS_GC_S_2_I_0"/> + <value value="388" name="A8XX_DEBUGBUS_TSEFE_GC_S_2_I_0"/> + <value value="389" name="A8XX_DEBUGBUS_TSEBE_GC_S_2_I_0"/> + <value value="390" name="A8XX_DEBUGBUS_RAS_GC_S_2_I_0"/> + <value value="391" name="A8XX_DEBUGBUS_LRZ_BR_S_2_I_0"/> + <value value="392" name="A8XX_DEBUGBUS_LRZ_BV_S_2_I_0"/> + <value value="393" name="A8XX_DEBUGBUS_VFDP_GC_S_2_I_0"/> + <value value="394" name="A8XX_DEBUGBUS_GPC_BR_S_2_I_0"/> + <value value="395" name="A8XX_DEBUGBUS_GPC_BV_S_2_I_0"/> + <value value="396" name="A8XX_DEBUGBUS_VPCFE_BR_S_2_I_0"/> + <value value="397" name="A8XX_DEBUGBUS_VPCFE_BV_S_2_I_0"/> + <value value="398" name="A8XX_DEBUGBUS_VPCBE_BR_S_2_I_0"/> + <value value="399" name="A8XX_DEBUGBUS_VPCBE_BV_S_2_I_0"/> + <value value="400" name="A8XX_DEBUGBUS_CCHE_GC_S_2_I_0"/> + <value value="401" name="A8XX_DEBUGBUS_DBGC_GC_S_2_I_0"/> + <value value="402" name="A8XX_DEBUGBUS_LARC_GC_S_2_I_0"/> + <value value="403" name="A8XX_DEBUGBUS_RBBM_GC_S_2_I_0"/> + <value value="404" name="A8XX_DEBUGBUS_CCRE_GC_S_2_I_0"/> + <value value="405" name="A8XX_DEBUGBUS_CGC_GC_S_2_I_0"/> + <value value="406" name="A8XX_DEBUGBUS_GMU_GC_S_2_I_0"/> + <value value="407" name="A8XX_DEBUGBUS_SLICE_GC_S_2_I_0"/> + <value value="408" name="A8XX_DEBUGBUS_HLSQ_SPTP_STAR_GC_S_2_I_0"/> + <value value="416" name="A8XX_DEBUGBUS_USP_GC_S_2_I_0"/> + <value value="417" name="A8XX_DEBUGBUS_USP_GC_S_2_I_1"/> + <value value="422" name="A8XX_DEBUGBUS_USPTP_GC_S_2_I_0"/> + <value value="423" name="A8XX_DEBUGBUS_USPTP_GC_S_2_I_1"/> + <value value="424" name="A8XX_DEBUGBUS_USPTP_GC_S_2_I_2"/> + <value value="425" name="A8XX_DEBUGBUS_USPTP_GC_S_2_I_3"/> + <value value="434" name="A8XX_DEBUGBUS_TP_GC_S_2_I_0"/> + <value value="435" name="A8XX_DEBUGBUS_TP_GC_S_2_I_1"/> + <value value="436" name="A8XX_DEBUGBUS_TP_GC_S_2_I_2"/> + <value value="437" name="A8XX_DEBUGBUS_TP_GC_S_2_I_3"/> + <value value="446" name="A8XX_DEBUGBUS_RB_GC_S_2_I_0"/> + <value value="447" name="A8XX_DEBUGBUS_RB_GC_S_2_I_1"/> + <value value="452" name="A8XX_DEBUGBUS_CCU_GC_S_2_I_0"/> + <value value="453" name="A8XX_DEBUGBUS_CCU_GC_S_2_I_1"/> + <value value="458" name="A8XX_DEBUGBUS_HLSQ_GC_S_2_I_0"/> + <value value="459" name="A8XX_DEBUGBUS_HLSQ_GC_S_2_I_1"/> + <value value="464" name="A8XX_DEBUGBUS_VFD_GC_S_2_I_0"/> + <value value="465" name="A8XX_DEBUGBUS_VFD_GC_S_2_I_1"/> +</enum> + +<enum name="a8xx_usptp_id"> + <value value="0" name="A8XX_uSPTP0"/> + <value value="1" name="A8XX_uSPTP1"/> + <value value="15" name="A8XX_SPTOP"/> +</enum> + +<enum name="a8xx_tex_swiz"> + <value name="A8XX_SWIZ_IDENTITY" value="0"/> + <value name="A8XX_SWIZ_ZERO" value="1"/> + <value name="A8XX_SWIZ_ONE" value="2"/> + <value name="A8XX_SWIZ_X" value="3"/> + <value name="A8XX_SWIZ_Y" value="4"/> + <value name="A8XX_SWIZ_Z" value="5"/> + <value name="A8XX_SWIZ_W" value="6"/> +</enum> + +</database> diff --git a/drivers/gpu/drm/msm/registers/adreno/adreno_common.xml b/drivers/gpu/drm/msm/registers/adreno/adreno_common.xml index 218ec8bb966e..79d204f1e400 100644 --- a/drivers/gpu/drm/msm/registers/adreno/adreno_common.xml +++ b/drivers/gpu/drm/msm/registers/adreno/adreno_common.xml @@ -11,6 +11,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <value name="A5XX" value="5"/> <value name="A6XX" value="6"/> <value name="A7XX" value="7"/> + <value name="A8XX" value="8"/> </enum> <enum name="adreno_pa_su_sc_draw"> @@ -397,4 +398,15 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <value value="0x7" name="TEX_PREFETCH_UNK7"/> </enum> +<enum name="adreno_pipe"> + <value value="0" name="PIPE_NONE"/> + <value value="1" name="PIPE_BR"/> + <value value="2" name="PIPE_BV"/> + <value value="3" name="PIPE_LPAC"/> + <value value="4" name="PIPE_AQE0"/> + <value value="5" name="PIPE_AQE1"/> + <value value="6" name="PIPE_DDE_BR"/> + <value value="7" name="PIPE_DDE_BV"/> +</enum> + </database> diff --git a/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml b/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml index 55a35182858c..51e9c94f5e37 100644 --- a/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml +++ b/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml @@ -6,96 +6,102 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <import file="adreno/adreno_common.xml"/> <enum name="vgt_event_type" varset="chip"> - <value name="VS_DEALLOC" value="0"/> - <value name="PS_DEALLOC" value="1" variants="A2XX-A6XX"/> - <value name="VS_DONE_TS" value="2"/> - <value name="PS_DONE_TS" value="3"/> + <value name="VS_DEALLOC" value="0x00" variants="A2XX-A5XX"/> + <value name="PS_DEALLOC" value="0x01" variants="A2XX-A5XX"/> + <value name="VS_DONE_TS" value="0x02" variants="A2XX-A5XX"/> + <value name="PS_DONE_TS" value="0x03" variants="A2XX-A5XX"/> <doc> Flushes dirty data from UCHE, and also writes a GPU timestamp to the address if one is provided. </doc> - <value name="CACHE_FLUSH_TS" value="4"/> - <value name="CONTEXT_DONE" value="5"/> - <value name="CACHE_FLUSH" value="6" variants="A2XX-A4XX"/> - <value name="VIZQUERY_START" value="7" variants="A2XX"/> - <value name="HLSQ_FLUSH" value="7" variants="A3XX-A4XX"/> - <value name="VIZQUERY_END" value="8" variants="A2XX"/> - <value name="SC_WAIT_WC" value="9" variants="A2XX"/> - <value name="WRITE_PRIMITIVE_COUNTS" value="9" variants="A6XX"/> - <value name="START_PRIMITIVE_CTRS" value="11" variants="A6XX"/> - <value name="STOP_PRIMITIVE_CTRS" value="12" variants="A6XX"/> + <value name="CACHE_FLUSH_TS" value="0x04"/> + <value name="CONTEXT_DONE" value="0x05"/> + <value name="CACHE_FLUSH" value="0x06" variants="A2XX-A4XX"/> + <value name="VIZQUERY_START" value="0x07" variants="A2XX"/> + <value name="HLSQ_FLUSH" value="0x07" variants="A3XX-A4XX"/> + <value name="VIZQUERY_END" value="0x08" variants="A2XX"/> + <value name="SC_WAIT_WC" value="0x09" variants="A2XX"/> + <value name="WRITE_PRIMITIVE_COUNTS" value="0x09" variants="A6XX-"/> + <value name="START_PRIMITIVE_CTRS" value="0x0b" variants="A6XX-"/> + <value name="STOP_PRIMITIVE_CTRS" value="0x0c" variants="A6XX-"/> <!-- Not sure that these 4 events don't have the same meaning as on A5XX+ --> - <value name="RST_PIX_CNT" value="13" variants="A2XX-A4XX"/> - <value name="RST_VTX_CNT" value="14" variants="A2XX-A4XX"/> - <value name="TILE_FLUSH" value="15" variants="A2XX-A4XX"/> - <value name="STAT_EVENT" value="16" variants="A2XX-A4XX"/> - <value name="CACHE_FLUSH_AND_INV_TS_EVENT" value="20" variants="A2XX-A4XX"/> + <value name="RST_PIX_CNT" value="0x0d" variants="A2XX-A4XX"/> + <value name="RST_VTX_CNT" value="0x0e" variants="A2XX-A4XX"/> + <value name="TILE_FLUSH" value="0x0f" variants="A2XX-A4XX"/> + <value name="STAT_EVENT" value="0x10" variants="A2XX-A4XX"/> + <value name="CACHE_FLUSH_AND_INV_TS_EVENT" value="0x14" variants="A2XX-A4XX"/> <doc> - If A6XX_RB_SAMPLE_COUNT_CONTROL.copy is true, writes OQ Z passed - sample counts to RB_SAMPLE_COUNT_ADDR. This writes to main + If A6XX_RB_SAMPLE_COUNTER_CNTL.copy is true, writes OQ Z passed + sample counts to RB_SAMPLE_COUNTER_BASE. This writes to main memory, skipping UCHE. </doc> - <value name="ZPASS_DONE" value="21"/> - <value name="CACHE_FLUSH_AND_INV_EVENT" value="22" variants="A2XX"/> + <value name="ZPASS_DONE" value="0x15"/> + <value name="CACHE_FLUSH_AND_INV_EVENT" value="0x16" variants="A2XX"/> <doc> Writes the GPU timestamp to the address that follows, once RB access and flushes are complete. </doc> - <value name="RB_DONE_TS" value="22" variants="A3XX-"/> + <value name="RB_DONE_TS" value="0x16" variants="A3XX-"/> - <value name="PERFCOUNTER_START" value="23" variants="A2XX-A4XX"/> - <value name="PERFCOUNTER_STOP" value="24" variants="A2XX-A4XX"/> - <value name="VS_FETCH_DONE" value="27"/> - <value name="FACENESS_FLUSH" value="28" variants="A2XX-A4XX"/> + <value name="PERFCOUNTER_START" value="0x17" variants="A2XX-A4XX"/> + <value name="PERFCOUNTER_STOP" value="0x18" variants="A2XX-A4XX"/> + <value name="VS_FETCH_DONE" value="0x1b" variants="A2XX-A5XX"/> + <value name="FACENESS_FLUSH" value="0x1c" variants="A2XX-A4XX"/> <!-- a5xx events --> - <value name="WT_DONE_TS" value="8" variants="A5XX-"/> - <value name="START_FRAGMENT_CTRS" value="13" variants="A5XX-"/> - <value name="STOP_FRAGMENT_CTRS" value="14" variants="A5XX-"/> - <value name="START_COMPUTE_CTRS" value="15" variants="A5XX-"/> - <value name="STOP_COMPUTE_CTRS" value="16" variants="A5XX-"/> - <value name="FLUSH_SO_0" value="17" variants="A5XX-"/> - <value name="FLUSH_SO_1" value="18" variants="A5XX-"/> - <value name="FLUSH_SO_2" value="19" variants="A5XX-"/> - <value name="FLUSH_SO_3" value="20" variants="A5XX-"/> + <value name="WT_DONE_TS" value="0x08" variants="A5XX-A6XX"/> + <value name="START_FRAGMENT_CTRS" value="0x0d" variants="A5XX-"/> + <value name="STOP_FRAGMENT_CTRS" value="0x0e" variants="A5XX-"/> + <value name="START_COMPUTE_CTRS" value="0x0f" variants="A5XX-"/> + <value name="STOP_COMPUTE_CTRS" value="0x10" variants="A5XX-"/> + <value name="FLUSH_SO_0" value="0x11" variants="A5XX-"/> + <value name="FLUSH_SO_1" value="0x12" variants="A5XX-"/> + <value name="FLUSH_SO_2" value="0x13" variants="A5XX-"/> + <value name="FLUSH_SO_3" value="0x14" variants="A5XX-"/> <doc> Invalidates depth attachment data from the CCU. We assume this happens in the last stage. </doc> - <value name="PC_CCU_INVALIDATE_DEPTH" value="24" variants="A5XX-"/> + <value name="PC_CCU_INVALIDATE_DEPTH" value="0x18" variants="A5XX-A6XX"/> <doc> Invalidates color attachment data from the CCU. We assume this happens in the last stage. </doc> - <value name="PC_CCU_INVALIDATE_COLOR" value="25" variants="A5XX-"/> + <value name="PC_CCU_INVALIDATE_COLOR" value="0x19" variants="A5XX-A6XX"/> <doc> Flushes the small cache used by CP_EVENT_WRITE::BLIT (which, along with its registers, would be better named RESOLVE). </doc> - <value name="PC_CCU_RESOLVE_TS" value="26" variants="A6XX"/> + <value name="PC_CCU_RESOLVE_TS" value="0x1a" variants="A6XX"/> <doc> Flushes depth attachment data from the CCU. We assume this happens in the last stage. </doc> - <value name="PC_CCU_FLUSH_DEPTH_TS" value="28" variants="A5XX-"/> + <value name="PC_CCU_FLUSH_DEPTH_TS" value="0x1c" variants="A5XX-A6XX"/> <doc> Flushes color attachment data from the CCU. We assume this happens in the last stage. </doc> - <value name="PC_CCU_FLUSH_COLOR_TS" value="29" variants="A5XX-"/> + <value name="PC_CCU_FLUSH_COLOR_TS" value="0x1d" variants="A5XX-A6XX"/> <doc> - 2D blit to resolve GMEM to system memory (skipping CCU) at the - end of a render pass. Compare to CP_BLIT's BLIT_OP_SCALE for - more general blitting. + Triggers a resolve (GMEM to sysmem) or unresolve (sysmem to + GMEM) or clear blit, depending on CCU programming. </doc> - <value name="BLIT" value="30" variants="A5XX-"/> + <value name="CCU_RESOLVE" value="0x1e" variants="A5XX-"/> + + <doc> + Flip between the primary and secondary LRZ buffers. This is used + for concurrent binning, so that BV can write to one buffer while + BR reads from the other. + </doc> + <value name="LRZ_FLIP_BUFFER" value="0x24" variants="A7XX-"/> <doc> Clears based on GRAS_LRZ_CNTL configuration, could clear @@ -108,43 +114,46 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> CUR_DIR_UNSET = 0x3 Clear of direction means setting the direction to CUR_DIR_UNSET. </doc> - <value name="LRZ_CLEAR" value="37" variants="A5XX-"/> - - <value name="LRZ_FLUSH" value="38" variants="A5XX-"/> - <value name="BLIT_OP_FILL_2D" value="39" variants="A5XX-"/> - <value name="BLIT_OP_COPY_2D" value="40" variants="A5XX-A6XX"/> - <value name="UNK_40" value="40" variants="A7XX"/> - <value name="BLIT_OP_SCALE_2D" value="42" variants="A5XX-"/> - <value name="CONTEXT_DONE_2D" value="43" variants="A5XX-"/> - <value name="UNK_2C" value="44" variants="A5XX-"/> - <value name="UNK_2D" value="45" variants="A5XX-"/> + <value name="LRZ_CLEAR" value="0x25" variants="A5XX-"/> + + <value name="LRZ_FLUSH_INVALIDATE" value="0x26" variants="A5XX-A6XX"/> + <value name="LRZ_CACHE_FLUSH" value="0x26" variants="A7XX-"/> + <value name="BLIT_OP_FILL_2D" value="0x27" variants="A5XX-A6XX"/> + <value name="BLIT_OP_COPY_2D" value="0x28" variants="A5XX-A6XX"/> + <value name="LRZ_CACHE_INVALIDATE" value="0x28" variants="A7XX-"/> + <value name="LRZ_Q_CACHE_INVALIDATE" value="0x29" variants="A7XX-"/> + <value name="BLIT_OP_SCALE_2D" value="0x2a" variants="A5XX-"/> + <value name="CONTEXT_DONE_2D" value="0x2b" variants="A5XX-"/> + <value name="VSC_BINNING_START" value="0x2c" variants="A5XX-"/> + <value name="VSC_BINNING_END" value="0x2d" variants="A5XX-"/> <!-- a6xx events --> <doc> Invalidates UCHE. </doc> - <value name="CACHE_INVALIDATE" value="49" variants="A6XX"/> + <value name="CACHE_INVALIDATE" value="0x31" variants="A6XX"/> - <value name="LABEL" value="63" variants="A6XX-"/> + <value name="DEBUG_LABEL" value="0x3f" variants="A6XX-"/> <!-- note, some of these are the same as a6xx, just named differently --> <doc> Doesn't seem to do anything </doc> - <value name="DUMMY_EVENT" value="1" variants="A7XX"/> - <value name="CCU_INVALIDATE_DEPTH" value="24" variants="A7XX"/> - <value name="CCU_INVALIDATE_COLOR" value="25" variants="A7XX"/> - <value name="CCU_RESOLVE_CLEAN" value="26" variants="A7XX"/> - <value name="CCU_FLUSH_DEPTH" value="28" variants="A7XX"/> - <value name="CCU_FLUSH_COLOR" value="29" variants="A7XX"/> - <value name="CCU_RESOLVE" value="30" variants="A7XX"/> - <value name="CCU_END_RESOLVE_GROUP" value="31" variants="A7XX"/> - <value name="CCU_CLEAN_DEPTH" value="32" variants="A7XX"/> - <value name="CCU_CLEAN_COLOR" value="33" variants="A7XX"/> - <value name="CACHE_RESET" value="48" variants="A7XX"/> - <value name="CACHE_CLEAN" value="49" variants="A7XX"/> + <value name="DUMMY_EVENT" value="0x01" variants="A7XX-"/> + <value name="CCU_INVALIDATE_DEPTH" value="0x18" variants="A7XX-"/> + <value name="CCU_INVALIDATE_COLOR" value="0x19" variants="A7XX-"/> + <value name="CCU_RESOLVE_CLEAN" value="0x1a" variants="A7XX-"/> + <value name="CCU_FLUSH_DEPTH" value="0x1c" variants="A7XX-"/> + <value name="CCU_FLUSH_COLOR" value="0x1d" variants="A7XX-"/> + <value name="CCU_END_RESOLVE_GROUP" value="0x1f" variants="A7XX-"/> + <value name="CCU_CLEAN_DEPTH" value="0x20" variants="A7XX-"/> + <value name="CCU_CLEAN_COLOR" value="0x21" variants="A7XX-"/> + <value name="CACHE_RESET" value="0x30" variants="A7XX-"/> + <value name="CACHE_CLEAN" value="0x31" variants="A7XX-"/> <!-- TODO: deal with name conflicts with other gens --> - <value name="CACHE_FLUSH7" value="50" variants="A7XX"/> - <value name="CACHE_INVALIDATE7" value="51" variants="A7XX"/> + <value name="CACHE_FLUSH7" value="0x32" variants="A7XX-"/> + <value name="CACHE_INVALIDATE7" value="0x33" variants="A7XX-"/> + <value name="DEPTH_BUFFER_FLIP" value="0x3d" variants="A8XX-"/> + <value name="CCH_FAST_CLEAR_CLEAN" value="0x1b" variants="A8XX-"/> </enum> <enum name="pc_di_primtype"> @@ -302,11 +311,11 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <value name="CP_EVENT_WRITE" value="0x46" variants="A2XX-A6XX"/> <value name="CP_EVENT_WRITE7" value="0x46" variants="A7XX-"/> <doc>generate a VS|PS_done event</doc> - <value name="CP_EVENT_WRITE_SHD" value="0x58"/> + <value name="CP_EVENT_WRITE_SHD" value="0x58" variants="A2XX"/> <doc>generate a cache flush done event</doc> - <value name="CP_EVENT_WRITE_CFL" value="0x59"/> + <value name="CP_EVENT_WRITE_CFL" value="0x59" variants="A2XX"/> <doc>generate a z_pass done event</doc> - <value name="CP_EVENT_WRITE_ZPD" value="0x5b"/> + <value name="CP_EVENT_WRITE_ZPD" value="0x5b" variants="A2XX"/> <doc> not sure the real name, but this seems to be what is used for opencl, instead of CP_DRAW_INDX.. @@ -327,9 +336,9 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <doc>load constant into chip and to memory</doc> <value name="CP_SET_CONSTANT" value="0x2d" variants="A2XX"/> <doc>load sequencer instruction memory (pointer-based)</doc> - <value name="CP_IM_LOAD" value="0x27"/> + <value name="CP_IM_LOAD" value="0x27" variants="A2XX"/> <doc>load sequencer instruction memory (code embedded in packet)</doc> - <value name="CP_IM_LOAD_IMMEDIATE" value="0x2b"/> + <value name="CP_IM_LOAD_IMMEDIATE" value="0x2b" variants="A2XX"/> <doc>load constants from a location in memory</doc> <value name="CP_LOAD_CONSTANT_CONTEXT" value="0x2e" variants="A2XX"/> <doc>selective invalidation of state pointers</doc> @@ -372,7 +381,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <value name="CP_LOAD_STATE" value="0x30" variants="A3XX"/> <value name="CP_LOAD_STATE4" value="0x30" variants="A4XX-A5XX"/> <doc>Conditionally load a IB based on a flag, prefetch enabled</doc> - <value name="CP_COND_INDIRECT_BUFFER_PFE" value="0x3a"/> + <value name="CP_COND_INDIRECT_BUFFER_PFE" value="0x3a" variants="A3XX-A5XX"/> <doc>Conditionally load a IB based on a flag, prefetch disabled</doc> <value name="CP_COND_INDIRECT_BUFFER_PFD" value="0x32" variants="A3XX"/> <doc>Load a buffer with pre-fetch enabled</doc> @@ -515,7 +524,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <!-- Seems to set the mode flags which control which CP_SET_DRAW_STATE packets are executed, based on their ENABLE_MASK values - + CP_SET_MODE w/ payload of 0x1 seems to cause CP_SET_DRAW_STATE packets w/ ENABLE_MASK & 0x6 to execute immediately --> @@ -538,7 +547,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <value name="CP_LOAD_STATE6_GEOM" value="0x32" variants="A6XX-"/> <value name="CP_LOAD_STATE6_FRAG" value="0x34" variants="A6XX-"/> <!-- - Note: For IBO state (Image/SSBOs) which have shared state across + Note: For UAV state (Image/SSBOs) which have shared state across shader stages, for 3d pipeline CP_LOAD_STATE6 is used. But for compute shaders, CP_LOAD_STATE6_FRAG is used. Possibly they are interchangable. @@ -567,7 +576,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <value name="IN_PREEMPT" value="0x0f" variants="A6XX-"/> <!-- TODO do these exist on A5xx? --> - <value name="CP_SCRATCH_WRITE" value="0x4c" variants="A6XX"/> + <value name="CP_SCRATCH_WRITE" value="0x4c" variants="A6XX-"/> <value name="CP_REG_TO_MEM_OFFSET_MEM" value="0x74" variants="A6XX-"/> <value name="CP_REG_TO_MEM_OFFSET_REG" value="0x72" variants="A6XX-"/> <value name="CP_WAIT_MEM_GTE" value="0x14" variants="A6XX"/> @@ -632,8 +641,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <value name="CP_BV_BR_COUNT_OPS" value="0x1b" variants="A7XX-"/> <doc> Clears, adds to local, or adds to global timestamp </doc> <value name="CP_MODIFY_TIMESTAMP" value="0x1c" variants="A7XX-"/> - <!-- similar to CP_CONTEXT_REG_BUNCH, but discards first two dwords?? --> - <value name="CP_CONTEXT_REG_BUNCH2" value="0x5d" variants="A7XX-"/> + <value name="CP_NON_CONTEXT_REG_BUNCH" value="0x5d" variants="A7XX-"/> <doc> Write to a scratch memory that is read by CP_REG_TEST with SOURCE_SCRATCH_MEM set. It's not the same scratch as scratch registers. @@ -650,6 +658,17 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <doc>Reset various on-chip state used for synchronization</doc> <value name="CP_RESET_CONTEXT_STATE" value="0x1f" variants="A7XX-"/> + + <doc>Invalidates the "CCHE" introduced on a740</doc> + <value name="CP_CCHE_INVALIDATE" value="0x3a" variants="A7XX-"/> + + <value name="CP_SCOPE_CNTL" value="0x6c" variants="A7XX-"/> + + <value name="CP_SKIP_IB_MODE" value="0x27" variants="A7XX-"/> + + <value name="CP_MEMORY_MAP_UPDATE" value="0x58" variants="A8XX-"/> + + <value name="CP_BARRIER" value="0x59" variants="A8XX-"/> </enum> @@ -792,14 +811,14 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <value name="SB6_GS_SHADER" value="0xb"/> <value name="SB6_FS_SHADER" value="0xc"/> <value name="SB6_CS_SHADER" value="0xd"/> - <value name="SB6_IBO" value="0xe"/> - <value name="SB6_CS_IBO" value="0xf"/> + <value name="SB6_UAV" value="0xe"/> + <value name="SB6_CS_UAV" value="0xf"/> </enum> <enum name="a6xx_state_type"> <value name="ST6_SHADER" value="0"/> <value name="ST6_CONSTANTS" value="1"/> <value name="ST6_UBO" value="2"/> - <value name="ST6_IBO" value="3"/> + <value name="ST6_UAV" value="3"/> </enum> <enum name="a6xx_state_src"> <value name="SS6_DIRECT" value="0"/> @@ -905,12 +924,6 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) </reg32> <stripe varset="chip" variants="A5XX-"> - <reg32 offset="4" name="4"> - <bitfield name="INDX_BASE_LO" low="0" high="31"/> - </reg32> - <reg32 offset="5" name="5"> - <bitfield name="INDX_BASE_HI" low="0" high="31"/> - </reg32> <reg64 offset="4" name="INDX_BASE" type="address"/> <reg32 offset="6" name="6"> <!-- max # of elements in index buffer --> @@ -1086,8 +1099,10 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <bitfield name="BINNING" pos="20" varset="chip" variants="A6XX-" type="boolean"/> <bitfield name="GMEM" pos="21" varset="chip" variants="A6XX-" type="boolean"/> <bitfield name="SYSMEM" pos="22" varset="chip" variants="A6XX-" type="boolean"/> - <bitfield name="GROUP_ID" low="24" high="28" type="uint"/> + <!-- high bit is 28 until a750: --> + <bitfield name="GROUP_ID" low="24" high="29" type="uint"/> </reg32> + <reg64 offset="1" name="ADDR" type="address"/> <reg32 offset="1" name="1"> <bitfield name="ADDR_LO" low="0" high="31" type="hex"/> </reg32> @@ -1121,39 +1136,63 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) </reg32> </domain> +<enum name="a7xx_abs_mask_mode"> + <value name="ABS_MASK" value="0x1"/> + <value name="NO_ABS_MASK" value="0x0"/> +</enum> + <domain name="CP_SET_BIN_DATA5" width="32"> <reg32 offset="0" name="0"> + <bitfield name="VSC_MASK" low="0" high="15" type="hex"> + <doc> + A mask of bins, starting at VSC_N, whose + visibility is OR'd together. A value of 0 is + interpreted as 1 (i.e. just use VSC_N for + visbility) for backwards compatibility. Only + exists on a7xx. + </doc> + </bitfield> <!-- equiv to PC_VSTREAM_CONTROL.SIZE on a3xx/a4xx: --> <bitfield name="VSC_SIZE" low="16" high="21" type="uint"/> <!-- equiv to PC_VSTREAM_CONTROL.N on a3xx/a4xx: --> <bitfield name="VSC_N" low="22" high="26" type="uint"/> - </reg32> - <!-- BIN_DATA_ADDR -> VSC_PIPE[p].DATA_ADDRESS --> - <reg32 offset="1" name="1"> - <bitfield name="BIN_DATA_ADDR_LO" low="0" high="31" type="hex"/> - </reg32> - <reg32 offset="2" name="2"> - <bitfield name="BIN_DATA_ADDR_HI" low="0" high="31" type="hex"/> - </reg32> - <!-- BIN_SIZE_ADDRESS -> VSC_SIZE_ADDRESS + (p * 4)--> - <reg32 offset="3" name="3"> - <bitfield name="BIN_SIZE_ADDRESS_LO" low="0" high="31"/> - </reg32> - <reg32 offset="4" name="4"> - <bitfield name="BIN_SIZE_ADDRESS_HI" low="0" high="31"/> - </reg32> - <!-- new on a6xx, where BIN_DATA_ADDR is the DRAW_STRM: --> - <reg32 offset="5" name="5"> - <bitfield name="BIN_PRIM_STRM_LO" low="0" high="31"/> - </reg32> - <reg32 offset="6" name="6"> - <bitfield name="BIN_PRIM_STRM_HI" low="0" high="31"/> - </reg32> - <!-- - a7xx adds a few more addresses to the end of the pkt - --> - <reg64 offset="7" name="7"/> - <reg64 offset="9" name="9"/> + <bitfield name="ABS_MASK" pos="28" type="a7xx_abs_mask_mode" addvariant="yes"> + <doc> + If this field is 1, VSC_MASK and VSC_N are + ignored and instead a new ordinal immediately + after specifies the full 32-bit mask of bins + to use. The mask is "absolute" instead of + relative to VSC_N. + </doc> + </bitfield> + </reg32> + <stripe varset="a7xx_abs_mask_mode" variants="NO_ABS_MASK"> + <!-- BIN_DATA_ADDR -> VSC_PIPE[p].DATA_ADDRESS --> + <reg64 offset="1" name="BIN_DATA_ADDR" type="address"/> + <!-- BIN_SIZE_ADDRESS -> VSC_SIZE_ADDRESS + (p * 4)--> + <reg64 offset="3" name="BIN_SIZE_ADDR" type="address"/> + <!-- new on a6xx, where BIN_DATA_ADDR is the DRAW_STRM: --> + <reg64 offset="5" name="BIN_PRIM_STRM" type="address"/> + <!-- + a7xx adds a few more addresses to the end of the pkt + --> + <reg64 offset="7" name="7"/> + <reg64 offset="9" name="9"/> + </stripe> + <stripe varset="a7xx_abs_mask_mode" variants="ABS_MASK"> + <reg32 offset="1" name="ABS_MASK"/> + <!-- BIN_DATA_ADDR -> VSC_PIPE[p].DATA_ADDRESS --> + <reg64 offset="2" name="BIN_DATA_ADDR" type="address"/> + <!-- BIN_SIZE_ADDRESS -> VSC_SIZE_ADDRESS + (p * 4)--> + <reg64 offset="4" name="BIN_SIZE_ADDR" type="address"/> + <!-- new on a6xx, where BIN_DATA_ADDR is the DRAW_STRM: --> + <reg64 offset="6" name="BIN_PRIM_STRM" type="address"/> + <!-- + a7xx adds a few more addresses to the end of the pkt + --> + <reg64 offset="8" name="8"/> + <reg64 offset="10" name="10"/> + </stripe> </domain> <domain name="CP_SET_BIN_DATA5_OFFSET" width="32"> @@ -1164,23 +1203,42 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) stream is recorded. </doc> <reg32 offset="0" name="0"> + <bitfield name="VSC_MASK" low="0" high="15" type="hex"/> <!-- equiv to PC_VSTREAM_CONTROL.SIZE on a3xx/a4xx: --> <bitfield name="VSC_SIZE" low="16" high="21" type="uint"/> <!-- equiv to PC_VSTREAM_CONTROL.N on a3xx/a4xx: --> <bitfield name="VSC_N" low="22" high="26" type="uint"/> + <bitfield name="ABS_MASK" pos="28" type="a7xx_abs_mask_mode" addvariant="yes"/> </reg32> - <!-- BIN_DATA_ADDR -> VSC_PIPE[p].DATA_ADDRESS --> - <reg32 offset="1" name="1"> - <bitfield name="BIN_DATA_OFFSET" low="0" high="31" type="uint"/> - </reg32> - <!-- BIN_SIZE_ADDRESS -> VSC_SIZE_ADDRESS + (p * 4)--> - <reg32 offset="2" name="2"> - <bitfield name="BIN_SIZE_OFFSET" low="0" high="31" type="uint"/> - </reg32> - <!-- BIN_DATA2_ADDR -> VSC_PIPE[p].DATA2_ADDRESS --> - <reg32 offset="3" name="3"> - <bitfield name="BIN_DATA2_OFFSET" low="0" high="31" type="uint"/> - </reg32> + <stripe varset="a7xx_abs_mask_mode" variants="NO_ABS_MASK"> + <!-- BIN_DATA_ADDR -> VSC_PIPE[p].DATA_ADDRESS --> + <reg32 offset="1" name="1"> + <bitfield name="BIN_DATA_OFFSET" low="0" high="31" type="uint"/> + </reg32> + <!-- BIN_SIZE_ADDRESS -> VSC_SIZE_ADDRESS + (p * 4)--> + <reg32 offset="2" name="2"> + <bitfield name="BIN_SIZE_OFFSET" low="0" high="31" type="uint"/> + </reg32> + <!-- BIN_DATA2_ADDR -> VSC_PIPE[p].DATA2_ADDRESS --> + <reg32 offset="3" name="3"> + <bitfield name="BIN_DATA2_OFFSET" low="0" high="31" type="uint"/> + </reg32> + </stripe> + <stripe varset="a7xx_abs_mask_mode" variants="ABS_MASK"> + <reg32 offset="1" name="ABS_MASK"/> + <!-- BIN_DATA_ADDR -> VSC_PIPE[p].DATA_ADDRESS --> + <reg32 offset="2" name="2"> + <bitfield name="BIN_DATA_OFFSET" low="0" high="31" type="uint"/> + </reg32> + <!-- BIN_SIZE_ADDRESS -> VSC_SIZE_ADDRESS + (p * 4)--> + <reg32 offset="3" name="3"> + <bitfield name="BIN_SIZE_OFFSET" low="0" high="31" type="uint"/> + </reg32> + <!-- BIN_DATA2_ADDR -> VSC_PIPE[p].DATA2_ADDRESS --> + <reg32 offset="4" name="4"> + <bitfield name="BIN_DATA2_OFFSET" low="0" high="31" type="uint"/> + </reg32> + </stripe> </domain> <domain name="CP_REG_RMW" width="32"> @@ -1198,6 +1256,9 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) </doc> <reg32 offset="0" name="0"> <bitfield name="DST_REG" low="0" high="17" type="hex"/> + <bitfield name="DST_SCRATCH" pos="19" type="boolean" varset="chip" variants="A7XX-"/> + <!-- skip implied CP_WAIT_FOR_IDLE + CP_WAIT_FOR_ME --> + <bitfield name="SKIP_WAIT_FOR_ME" pos="23" type="boolean" varset="chip" variants="A7XX-"/> <bitfield name="ROTATE" low="24" high="28" type="uint"/> <bitfield name="SRC1_ADD" pos="29" type="boolean"/> <bitfield name="SRC1_IS_REG" pos="30" type="boolean"/> @@ -1211,7 +1272,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) </reg32> </domain> -<domain name="CP_REG_TO_MEM" width="32"> +<domain name="CP_REG_TO_MEM" width="32" prefix="chip"> <reg32 offset="0" name="0"> <bitfield name="REG" low="0" high="17" type="hex"/> <!-- number of registers/dwords copied is max(CNT, 1). --> @@ -1219,12 +1280,12 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <bitfield name="64B" pos="30" type="boolean"/> <bitfield name="ACCUMULATE" pos="31" type="boolean"/> </reg32> - <reg32 offset="1" name="1"> - <bitfield name="DEST" low="0" high="31"/> - </reg32> - <reg32 offset="2" name="2" varset="chip" variants="A5XX-"> - <bitfield name="DEST_HI" low="0" high="31"/> - </reg32> + <stripe varset="chip" variants="A2XX-A4XX"> + <reg32 offset="1" name="DEST" type="address"/> + </stripe> + <stripe varset="chip" variants="A5XX-"> + <reg64 offset="1" name="DEST" type="address"/> + </stripe> </domain> <domain name="CP_REG_TO_MEM_OFFSET_REG" width="32"> @@ -1240,12 +1301,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <bitfield name="64B" pos="30" type="boolean"/> <bitfield name="ACCUMULATE" pos="31" type="boolean"/> </reg32> - <reg32 offset="1" name="1"> - <bitfield name="DEST" low="0" high="31"/> - </reg32> - <reg32 offset="2" name="2" varset="chip" variants="A5XX-"> - <bitfield name="DEST_HI" low="0" high="31"/> - </reg32> + <reg64 offset="1" name="DEST" type="waddress"/> <reg32 offset="3" name="3"> <bitfield name="OFFSET0" low="0" high="17" type="hex"/> <bitfield name="OFFSET0_SCRATCH" pos="19" type="boolean"/> @@ -1265,18 +1321,8 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <bitfield name="64B" pos="30" type="boolean"/> <bitfield name="ACCUMULATE" pos="31" type="boolean"/> </reg32> - <reg32 offset="1" name="1"> - <bitfield name="DEST" low="0" high="31"/> - </reg32> - <reg32 offset="2" name="2" varset="chip" variants="A5XX-"> - <bitfield name="DEST_HI" low="0" high="31"/> - </reg32> - <reg32 offset="3" name="3"> - <bitfield name="OFFSET_LO" low="0" high="31" type="hex"/> - </reg32> - <reg32 offset="4" name="4"> - <bitfield name="OFFSET_HI" low="0" high="31" type="hex"/> - </reg32> + <reg64 offset="1" name="DEST" type="waddress"/> + <reg64 offset="3" name="OFFSET" type="waddress"/> </domain> <domain name="CP_MEM_TO_REG" width="32"> @@ -1289,12 +1335,12 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <!-- does the same thing as CP_MEM_TO_MEM::UNK31 --> <bitfield name="UNK31" pos="31" type="boolean"/> </reg32> - <reg32 offset="1" name="1"> - <bitfield name="SRC" low="0" high="31"/> - </reg32> - <reg32 offset="2" name="2" varset="chip" variants="A5XX-"> - <bitfield name="SRC_HI" low="0" high="31"/> - </reg32> + <stripe varset="chip" variants="A2XX-A4XX"> + <reg32 offset="1" name="SRC" type="address"/> + </stripe> + <stripe varset="chip" variants="A5XX-"> + <reg64 offset="1" name="SRC" type="address"/> + </stripe> </domain> <domain name="CP_MEM_TO_MEM" width="32"> @@ -1314,6 +1360,10 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <!-- some other kind of wait --> <bitfield name="UNK31" pos="31" type="boolean"/> </reg32> + <reg64 offset="1" name="DST" type="waddress"/> + <reg64 offset="3" name="SRC_A" type="address"/> + <reg64 offset="5" name="SRC_B" type="address"/> + <reg64 offset="7" name="SRC_C" type="address"/> <!-- followed by sequence of addresses.. the first is the destination and the rest are N src addresses which are @@ -1348,6 +1398,8 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <bitfield name="SCRATCH" low="20" high="22" type="uint"/> <!-- number of registers/dwords copied is CNT + 1. --> <bitfield name="CNT" low="24" high="26" type="uint"/> + <!-- skip implied CP_WAIT_FOR_IDLE + CP_WAIT_FOR_ME --> + <bitfield name="SKIP_WAIT_FOR_ME" pos="27" type="boolean" varset="chip" variants="A7XX-"/> </reg32> </domain> @@ -1370,12 +1422,12 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) </domain> <domain name="CP_MEM_WRITE" width="32"> - <reg32 offset="0" name="0"> - <bitfield name="ADDR_LO" low="0" high="31"/> - </reg32> - <reg32 offset="1" name="1"> - <bitfield name="ADDR_HI" low="0" high="31"/> - </reg32> + <stripe varset="chip" variants="A2XX-A4XX"> + <reg32 offset="0" name="ADDR" type="address"/> + </stripe> + <stripe varset="chip" variants="A5XX-"> + <reg64 offset="0" name="ADDR" type="address"/> + </stripe> <!-- followed by the DWORDs to write --> </domain> @@ -1427,24 +1479,14 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <bitfield name="POLL" low="4" high="5" type="poll_memory_type"/> <bitfield name="WRITE_MEMORY" pos="8" type="boolean"/> </reg32> - <reg32 offset="1" name="1"> - <bitfield name="POLL_ADDR_LO" low="0" high="31" type="hex"/> - </reg32> - <reg32 offset="2" name="2"> - <bitfield name="POLL_ADDR_HI" low="0" high="31" type="hex"/> - </reg32> + <reg64 offset="1" name="POLL_ADDR" type="address"/> <reg32 offset="3" name="3"> <bitfield name="REF" low="0" high="31"/> </reg32> <reg32 offset="4" name="4"> <bitfield name="MASK" low="0" high="31"/> </reg32> - <reg32 offset="5" name="5"> - <bitfield name="WRITE_ADDR_LO" low="0" high="31" type="hex"/> - </reg32> - <reg32 offset="6" name="6"> - <bitfield name="WRITE_ADDR_HI" low="0" high="31" type="hex"/> - </reg32> + <reg64 offset="5" name="WRITE_ADDR" type="waddress"/> <reg32 offset="7" name="7"> <bitfield name="WRITE_DATA" low="0" high="31"/> </reg32> @@ -1459,12 +1501,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <!-- Reserved for flags, presumably? Unused in FW --> <bitfield name="RESERVED" low="0" high="31" type="hex"/> </reg32> - <reg32 offset="1" name="1"> - <bitfield name="POLL_ADDR_LO" low="0" high="31" type="hex"/> - </reg32> - <reg32 offset="2" name="2"> - <bitfield name="POLL_ADDR_HI" low="0" high="31" type="hex"/> - </reg32> + <reg64 offset="1" name="POLL_ADDR" type="address"/> <reg32 offset="3" name="3"> <bitfield name="REF" low="0" high="31"/> </reg32> @@ -1482,12 +1519,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <bitfield name="POLL" low="4" high="5" type="poll_memory_type"/> <bitfield name="WRITE_MEMORY" pos="8" type="boolean"/> </reg32> - <reg32 offset="1" name="1"> - <bitfield name="POLL_ADDR_LO" low="0" high="31" type="hex"/> - </reg32> - <reg32 offset="2" name="2"> - <bitfield name="POLL_ADDR_HI" low="0" high="31" type="hex"/> - </reg32> + <reg64 offset="1" name="POLL_ADDR" type="address"/> <reg32 offset="3" name="3"> <bitfield name="REF" low="0" high="31"/> </reg32> @@ -1621,12 +1653,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) TODO what is gpuaddr for, seems to be all 0's.. maybe needed for context switch? --> - <reg32 offset="1" name="1"> - <bitfield name="ADDR_0_LO" low="0" high="31"/> - </reg32> - <reg32 offset="2" name="2"> - <bitfield name="ADDR_0_HI" low="0" high="31"/> - </reg32> + <reg64 offset="1" name="ADDR" type="waddress"/> <reg32 offset="3" name="3"> <!-- ??? --> </reg32> @@ -1655,8 +1682,8 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <bitfield name="WRITE_SAMPLE_COUNT" pos="12" type="boolean"/> <!-- Write sample count at (iova + 16) --> <bitfield name="SAMPLE_COUNT_END_OFFSET" pos="13" type="boolean"/> - <!-- *(iova + 8) = *(iova + 16) - *iova --> - <bitfield name="WRITE_SAMPLE_COUNT_DIFF" pos="14" type="boolean"/> + <!-- *(iova + 8) += *(iova + 16) - *iova --> + <bitfield name="WRITE_ACCUM_SAMPLE_COUNT_DIFF" pos="14" type="boolean"/> <!-- Next 4 flags are valid to set only when concurrent binning is enabled --> <!-- Increment 16b BV counter. Valid only in BV pipe --> @@ -1670,15 +1697,11 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <bitfield name="WRITE_DST" pos="24" type="event_write_dst" addvariant="yes"/> <!-- Writes into WRITE_DST from WRITE_SRC. RB_DONE_TS requires WRITE_ENABLED. --> <bitfield name="WRITE_ENABLED" pos="27" type="boolean"/> + <bitfield name="IRQ" pos="31" type="boolean"/> </reg32> <stripe varset="event_write_dst" variants="EV_DST_RAM"> - <reg32 offset="1" name="1"> - <bitfield name="ADDR_0_LO" low="0" high="31"/> - </reg32> - <reg32 offset="2" name="2"> - <bitfield name="ADDR_0_HI" low="0" high="31"/> - </reg32> + <reg64 offset="1" name="1" type="waddress"/> <reg32 offset="3" name="3"> <bitfield name="PAYLOAD_0" low="0" high="31"/> </reg32> @@ -1745,9 +1768,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <reg32 offset="0" name="0"> </reg32> <stripe varset="chip" variants="A4XX"> - <reg32 offset="1" name="1"> - <bitfield name="ADDR" low="0" high="31"/> - </reg32> + <reg32 offset="1" name="ADDR" type="address"/> <reg32 offset="2" name="2"> <!-- localsize is value minus one: --> <bitfield name="LOCALSIZEX" low="2" high="11" type="uint"/> @@ -1756,12 +1777,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) </reg32> </stripe> <stripe varset="chip" variants="A5XX-"> - <reg32 offset="1" name="1"> - <bitfield name="ADDR_LO" low="0" high="31"/> - </reg32> - <reg32 offset="2" name="2"> - <bitfield name="ADDR_HI" low="0" high="31"/> - </reg32> + <reg64 offset="1" name="ADDR" type="address"/> <reg32 offset="3" name="3"> <!-- localsize is value minus one: --> <bitfield name="LOCALSIZEX" low="2" high="11" type="uint"/> @@ -1773,40 +1789,91 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <domain name="CP_SET_MARKER" width="32" varset="chip" prefix="chip" variants="A6XX-"> <doc>Tell CP the current operation mode, indicates save and restore procedure</doc> + <enum name="set_marker_mode"> + <value value="0" name="SET_RENDER_MODE"/> + <!-- IFPC - inter-frame power collapse --> + <value value="1" name="SET_IFPC_MODE"/> + </enum> + <enum name="a6xx_ifpc_mode"> + <value value="0" name="IFPC_ENABLE"/> + <value value="1" name="IFPC_DISABLE"/> + </enum> <enum name="a6xx_marker"> - <value value="1" name="RM6_BYPASS"/> - <value value="2" name="RM6_BINNING"/> - <value value="4" name="RM6_GMEM"/> - <value value="5" name="RM6_ENDVIS"/> - <value value="6" name="RM6_RESOLVE"/> - <value value="7" name="RM6_YIELD"/> + <value value="1" name="RM6_DIRECT_RENDER"/> + <value value="2" name="RM6_BIN_VISIBILITY"/> + <value value="3" name="RM6_BIN_DIRECT"/> + <value value="4" name="RM6_BIN_RENDER_START"/> + <value value="5" name="RM6_BIN_END_OF_DRAWS"/> + <value value="6" name="RM6_BIN_RESOLVE"/> + <value value="7" name="RM6_BIN_RENDER_END"/> <value value="8" name="RM6_COMPUTE"/> - <value value="0xc" name="RM6_BLIT2DSCALE"/> <!-- no-op (at least on current sqe fw) --> + <value value="12" name="RM6_BLIT2DSCALE"/> <!-- no-op (at least on current sqe fw) --> <!-- These values come from a6xx_set_marker() in the downstream kernel, and they can only be set by the kernel --> - <value value="0xd" name="RM6_IB1LIST_START"/> - <value value="0xe" name="RM6_IB1LIST_END"/> - <!-- IFPC - inter-frame power collapse --> - <value value="0x100" name="RM6_IFPC_ENABLE"/> - <value value="0x101" name="RM6_IFPC_DISABLE"/> + <value value="13" name="RM6_IB1LIST_START"/> + <value value="14" name="RM6_IB1LIST_END"/> + <value value="15" name="RM7_BIN_VISIBILITY_END"/> + + <!-- new in a8xx: --> + <value value="32" name="RM8_DEPTH_PASS_START"/> + <value value="33" name="RM8_DEPTH_PASS_END"/> + <value value="34" name="RM8_SET_RENDER_TARGET"/> + <value value="35" name="RM8_PGMEM_ON"/> + <value value="36" name="RM8_PGMEM_OFF"/> </enum> - <reg32 offset="0" name="0"> - <!-- - NOTE: blob driver and some versions of freedreno/turnip set - b4, which is unused (at least by current sqe fw), but interferes - with parsing if we extend the size of the bitfield to include - b8 (only sent by kernel mode driver). Really, the way the - parsing works in the firmware, only b0-b3 are considered, but - if b8 is set, the low bits are interpreted differently. To - model this, without getting confused by spurious b4, this is - described as two overlapping bitfields: - --> - <bitfield name="MODE" low="0" high="8" type="a6xx_marker"/> - <bitfield name="MARKER" low="0" high="3" type="a6xx_marker"/> - </reg32> + <stripe varset="chip" variants="A6XX-A7XX"> + <reg32 offset="0" name="0"> + <!-- if b8 is set, the low bits are interpreted differently (and b4 ignored) --> + <bitfield name="MARKER_MODE" pos="8" type="set_marker_mode" addvariant="yes"/> + + + <bitfield name="MODE" low="0" high="3" type="a6xx_marker" varset="set_marker_mode" variants="SET_RENDER_MODE"/> + <!-- used by preemption to determine if GMEM needs to be saved or not --> + <bitfield name="USES_GMEM" pos="4" type="boolean" varset="set_marker_mode" variants="SET_RENDER_MODE"/> + + + <bitfield name="IFPC_MODE" pos="0" type="a6xx_ifpc_mode" varset="set_marker_mode" variants="SET_IFPC_MODE"/> + + + <!-- + CP_SET_MARKER is used with these bits to create a + critical section around a workaround for ray tracing. + The workaround happens after BVH building, and appears + to invalidate the RTU's BVH node cache. It makes sure + that only one of BR/BV/LPAC is executing the + workaround at a time, and no draws using RT on BV/LPAC + are executing while the workaround is executed on BR (or + vice versa, that no draws on BV/BR using RT are executed + while the workaround executes on LPAC), by + hooking subsequent CP_EVENT_WRITE/CP_DRAW_*/CP_EXEC_CS. + The blob usage is: + + + CP_SET_MARKER(RT_WA_START) + ... workaround here ... + CP_SET_MARKER(RT_WA_END) + ... + CP_SET_MARKER(SHADER_USES_RT) + CP_DRAW_INDX(...) or CP_EXEC_CS(...) + --> + <bitfield name="SHADER_USES_RT" pos="9" type="boolean" variants="A7XX-"/> + <bitfield name="RT_WA_START" pos="10" type="boolean" variants="A7XX-"/> + <bitfield name="RT_WA_END" pos="11" type="boolean" variants="A7XX-"/> + </reg32> + </stripe> + <stripe varset="chip" variants="A8XX-"> + <reg32 offset="0" name="0"> + <!-- if b8 is set, the low bits are interpreted differently (and b4 ignored) --> + <bitfield name="MARKER_MODE" pos="8" type="set_marker_mode" addvariant="yes"/> + <bitfield name="MODE" low="0" high="6" type="a6xx_marker" varset="set_marker_mode" variants="SET_RENDER_MODE"/> + <bitfield name="USES_GMEM" pos="7" type="boolean" varset="set_marker_mode" variants="SET_RENDER_MODE"/> + <bitfield name="IFPC_MODE" pos="0" type="a6xx_ifpc_mode" varset="set_marker_mode" variants="SET_IFPC_MODE"/> + <!-- idk if the RT w/a fields apply to a8xx as well --> + </reg32> + </stripe> </domain> <domain name="CP_SET_PSEUDO_REG" width="32" varset="chip" prefix="chip" variants="A6XX-"> @@ -1832,9 +1899,9 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) If concurrent binning is disabled then BR also does binning so it will also write the "real" registers in BR. --> - <value value="8" name="DRAW_STRM_ADDRESS"/> - <value value="9" name="DRAW_STRM_SIZE_ADDRESS"/> - <value value="10" name="PRIM_STRM_ADDRESS"/> + <value value="8" name="VSC_PIPE_DATA_DRAW_BASE"/> + <value value="9" name="VSC_SIZE_BASE"/> + <value value="10" name="VSC_PIPE_DATA_PRIM_BASE"/> <value value="11" name="UNK_STRM_ADDRESS"/> <value value="12" name="UNK_STRM_SIZE_ADDRESS"/> @@ -1935,11 +2002,11 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) a bitmask of which modes pass the test. --> - <!-- RM6_BINNING --> + <!-- RM6_BIN_VISIBILITY --> <bitfield name="BINNING" pos="25" variants="RENDER_MODE" type="boolean"/> <!-- all others --> <bitfield name="GMEM" pos="26" variants="RENDER_MODE" type="boolean"/> - <!-- RM6_BYPASS --> + <!-- RM6_DIRECT_RENDER --> <bitfield name="SYSMEM" pos="27" variants="RENDER_MODE" type="boolean"/> <bitfield name="BV" pos="25" variants="THREAD_MODE" type="boolean"/> @@ -2014,10 +2081,10 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <domain name="CP_SET_AMBLE" width="32"> <doc> - Used by the userspace and kernel drivers to set various IB's - which are executed during context save/restore for handling - state that isn't restored by the context switch routine itself. - </doc> + Used by the userspace and kernel drivers to set various IB's + which are executed during context save/restore for handling + state that isn't restored by the context switch routine itself. + </doc> <enum name="amble_type"> <value name="PREAMBLE_AMBLE_TYPE" value="0"> <doc>Executed unconditionally when switching back to the context.</doc> @@ -2030,6 +2097,14 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) payload *and* skipsaverestore is set. This is expected to restore static register values not saved when skipsaverestore is set. + + On BV, a skipsaverestore preemption is triggered + and this preamble type is executed whenever a + CP_THREAD_CONTROL that synchronizes threads + happens. This can be explicitly via + SYNC_THREADS, or implicitly when the value of + CONCURRENT_BIN_DISABLE changes from the previous + thread control. </doc> </value> <value name="POSTAMBLE_AMBLE_TYPE" value="2"> @@ -2047,12 +2122,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) </doc> </value> </enum> - <reg32 offset="0" name="0"> - <bitfield name="ADDR_LO" low="0" high="31"/> - </reg32> - <reg32 offset="1" name="1"> - <bitfield name="ADDR_HI" low="0" high="31"/> - </reg32> + <reg64 offset="0" name="ADDR" type="address"/> <reg32 offset="2" name="2"> <bitfield name="DWORDS" low="0" high="19" type="uint"/> <bitfield name="TYPE" low="20" high="21" type="amble_type"/> @@ -2087,12 +2157,12 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <value name="UNK_EVENT_WRITE" value="0x4"/> <doc> Tracks GRAS_LRZ_CNTL::GREATER, GRAS_LRZ_CNTL::DIR, and - GRAS_LRZ_DEPTH_VIEW with previous values, and if one of + GRAS_LRZ_VIEW_INFO with previous values, and if one of the following is true: - GRAS_LRZ_CNTL::GREATER has changed - GRAS_LRZ_CNTL::DIR has changed, the old value is not CUR_DIR_GE, and the new value is not CUR_DIR_DISABLED - - GRAS_LRZ_DEPTH_VIEW has changed + - GRAS_LRZ_VIEW_INFO has changed then it does a LRZ_FLUSH with GRAS_LRZ_CNTL::ENABLE forced to 1. Only exists in a650_sqe.fw. @@ -2207,7 +2277,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <domain name="CP_MEM_TO_SCRATCH_MEM" width="32"> <doc> - Best guess is that it is a faster way to fetch all the VSC_STATE registers + Best guess is that it is a faster way to fetch all the VSC_CHANNEL_VISIBILITY registers and keep them in a local scratch memory instead of fetching every time when skipping IBs. </doc> @@ -2255,9 +2325,121 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) <reg32 offset="0" name="0"> <bitfield name="CLEAR_ON_CHIP_TS" pos="0" type="boolean"/> <bitfield name="CLEAR_RESOURCE_TABLE" pos="1" type="boolean"/> - <bitfield name="CLEAR_GLOBAL_LOCAL_TS" pos="2" type="boolean"/> + <bitfield name="CLEAR_BV_BR_COUNTER" pos="2" type="boolean"/> + <bitfield name="RESET_GLOBAL_LOCAL_TS" pos="3" type="boolean"/> + </reg32> +</domain> + +<domain name="CP_SCOPE_CNTL" width="32"> + <enum name="cp_scope"> + <value value="0" name="INTERRUPTS"/> + </enum> + <reg32 offset="0" name="0"> + <bitfield name="DISABLE_PREEMPTION" pos="0" type="boolean"/> + <bitfield low="28" high="31" name="SCOPE" type="cp_scope"/> + </reg32> +</domain> + +<domain name="CP_INDIRECT_BUFFER" width="32" varset="chip" prefix="chip" variants="A5XX-"> + <reg64 offset="0" name="IB_BASE" type="address"/> + <reg32 offset="2" name="2"> + <bitfield name="IB_SIZE" low="0" high="19"/> </reg32> </domain> +<domain name="CP_RESOURCE_LIST" width="32"> + <doc> + A7xx introduces the "resource table" which is managed by + CP_RESOURCE_LIST. It is used to synchronize BR and BV access + to resources such as LRZ buffers. + + The resource table consists of resources that are in-use by BR. + Each "resource" has a base address, which is + usually a pointer but is treated by the HW as an opaque handle, + a read/write bit, and a timestamp when it was last used. + Resources are removed from the table upon event completion when + a special CP_EVENT_WRITE::CLEAR_RENDER_RESOURCE bit is set, which + will remove all resources with a timestamp up to the current + timestamp. + + CP_RESOURCE_LIST first specifies a list of BV resources. For + each BV resource, the HW will check if there is a corresponding + BR resource in the table, and if at least one of the BV and BR + resources is marked WRITE then it will stall until the BR + resource is removed. + + It then specifies a list of BR resources. These will be added to + the resource table, unless there is an overflow in which case + the designated overflow register will have bit 0 set. Overflow + should cause the next binning pass to stall until BR is done, + effectively disabling concurrent binning. + + CP_RESOURCE_LIST must be executed by BV. BR resources are added + by BV and removed by BR. + + There is a separate table for "LRZ resources." These behave a + bit differently: specifying an LRZ resource via BV_RES_LRZ + stalls on any matching resource existing and then adds it to the + table, making it both a BV and BR resource in one. There is a + separate CLEAR_LRZ_RESOURCE bit for removing resources from the + LRZ table, and it only removes one resource given by a base + address passed to CP_EVENT_WRITE. Therefore timestamps are + unnecessary. + </doc> + <reg32 offset="0" name="BV_COUNT" type="uint"/> + <doc> + What follows is a list of CP_BV_RESOURCE and then CP_RESOURCE_LIST_BR. + </doc> +</domain> + +<domain name="CP_BV_RESOURCE" width="32"> + <doc> + BV resources don't go in the table. Instead CP waits until any + corresponding BR resources with the same base pointer are + finished before the packet completes. + </doc> + <enum name="cp_bv_resource_encoding"> + <value value="0" name="BV_RES_DIRECT"/> + <doc> + INDIRECT resources are encoded as a 32b offset + 3b + bindless base selector. The offset is added to the given + BINDLESS_BASE pseudoregister and then the 64b value + fetched there is used as the pointer. + </doc> + <value value="1" name="BV_RES_INDIRECT_READ"/> + <value value="2" name="BV_RES_LRZ"/> + <value value="3" name="BV_RES_INDIRECT_WRITE"/> + </enum> + <reg64 offset="0" name="0"> + <bitfield name="BASE_ADDR" low="1" high="61" shr="1" type="address"/> + <bitfield name="WRITE" pos="0" type="boolean"/> + <bitfield name="ENCODING" low="62" high="63" type="cp_bv_resource_encoding"/> + </reg64> +</domain> + +<domain name="CP_RESOURCE_LIST_BR" width="32"> + <reg32 offset="0" name="0"> + <bitfield name="BR_COUNT" low="0" high="23" type="uint"/> + <bitfield name="OVERFLOW_ONCHIP_ADDR" low="24" high="26"/> + <bitfield name="OVERFLOW" pos="31" type="boolean"/> + </reg32> + <doc> + What follows is a list of CP_BR_RESOURCE. + </doc> +</domain> + +<domain name="CP_BR_RESOURCE" width="32"> + <enum name="cp_br_resource_encoding"> + <value value="0" name="BR_RES_DIRECT"/> + <value value="2" name="BR_RES_INDIRECT_READ"/> + <value value="3" name="BR_RES_INDIRECT_WRITE"/> <!-- set WRITE bit --> + </enum> + <reg64 offset="0" name="0"> + <bitfield name="BASE_ADDR" low="1" high="61" shr="1" type="address"/> + <bitfield name="WRITE" pos="0" type="boolean"/> + <bitfield name="ENCODING" low="62" high="63" type="cp_br_resource_encoding"/> + </reg64> +</domain> + </database> diff --git a/drivers/gpu/drm/msm/registers/display/dsi.xml b/drivers/gpu/drm/msm/registers/display/dsi.xml index 501ffc585a9f..c7a7b633d747 100644 --- a/drivers/gpu/drm/msm/registers/display/dsi.xml +++ b/drivers/gpu/drm/msm/registers/display/dsi.xml @@ -159,28 +159,28 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <bitfield name="RGB_SWAP" low="12" high="14" type="dsi_rgb_swap"/> </reg32> <reg32 offset="0x00020" name="ACTIVE_H"> - <bitfield name="START" low="0" high="11" type="uint"/> - <bitfield name="END" low="16" high="27" type="uint"/> + <bitfield name="START" low="0" high="15" type="uint"/> + <bitfield name="END" low="16" high="31" type="uint"/> </reg32> <reg32 offset="0x00024" name="ACTIVE_V"> - <bitfield name="START" low="0" high="11" type="uint"/> - <bitfield name="END" low="16" high="27" type="uint"/> + <bitfield name="START" low="0" high="15" type="uint"/> + <bitfield name="END" low="16" high="31" type="uint"/> </reg32> <reg32 offset="0x00028" name="TOTAL"> - <bitfield name="H_TOTAL" low="0" high="11" type="uint"/> - <bitfield name="V_TOTAL" low="16" high="27" type="uint"/> + <bitfield name="H_TOTAL" low="0" high="15" type="uint"/> + <bitfield name="V_TOTAL" low="16" high="31" type="uint"/> </reg32> <reg32 offset="0x0002c" name="ACTIVE_HSYNC"> - <bitfield name="START" low="0" high="11" type="uint"/> - <bitfield name="END" low="16" high="27" type="uint"/> + <bitfield name="START" low="0" high="15" type="uint"/> + <bitfield name="END" low="16" high="31" type="uint"/> </reg32> <reg32 offset="0x00030" name="ACTIVE_VSYNC_HPOS"> - <bitfield name="START" low="0" high="11" type="uint"/> - <bitfield name="END" low="16" high="27" type="uint"/> + <bitfield name="START" low="0" high="15" type="uint"/> + <bitfield name="END" low="16" high="31" type="uint"/> </reg32> <reg32 offset="0x00034" name="ACTIVE_VSYNC_VPOS"> - <bitfield name="START" low="0" high="11" type="uint"/> - <bitfield name="END" low="16" high="27" type="uint"/> + <bitfield name="START" low="0" high="15" type="uint"/> + <bitfield name="END" low="16" high="31" type="uint"/> </reg32> <reg32 offset="0x00038" name="CMD_DMA_CTRL"> @@ -209,8 +209,8 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <bitfield name="WORD_COUNT" low="16" high="31" type="uint"/> </reg32> <reg32 offset="0x00058" name="CMD_MDP_STREAM0_TOTAL"> - <bitfield name="H_TOTAL" low="0" high="11" type="uint"/> - <bitfield name="V_TOTAL" low="16" high="27" type="uint"/> + <bitfield name="H_TOTAL" low="0" high="15" type="uint"/> + <bitfield name="V_TOTAL" low="16" high="31" type="uint"/> </reg32> <reg32 offset="0x0005c" name="CMD_MDP_STREAM1_CTRL"> <bitfield name="DATA_TYPE" low="0" high="5" type="uint"/> diff --git a/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml b/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml index d54b72f92449..f41516dd0567 100644 --- a/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml +++ b/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml @@ -9,15 +9,33 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <reg32 offset="0x00004" name="REVISION_ID1"/> <reg32 offset="0x00008" name="REVISION_ID2"/> <reg32 offset="0x0000c" name="REVISION_ID3"/> - <reg32 offset="0x00010" name="CLK_CFG0"/> - <reg32 offset="0x00014" name="CLK_CFG1"/> + <reg32 offset="0x00010" name="CLK_CFG0"> + <bitfield name="DIV_CTRL_3_0" low="0" high="3" type="uint"/> + <bitfield name="DIV_CTRL_7_4" low="4" high="7" type="uint"/> + </reg32> + <reg32 offset="0x00014" name="CLK_CFG1"> + <bitfield name="CLK_EN" pos="5" type="boolean"/> + <bitfield name="CLK_EN_SEL" pos="4" type="boolean"/> + <bitfield name="BITCLK_SEL" low="2" high="3" type="uint"/> + <bitfield name="DSICLK_SEL" low="0" high="1" type="uint"/> + </reg32> <reg32 offset="0x00018" name="GLBL_CTRL"/> <reg32 offset="0x0001c" name="RBUF_CTRL"/> <reg32 offset="0x00020" name="VREG_CTRL_0"/> - <reg32 offset="0x00024" name="CTRL_0"/> + <reg32 offset="0x00024" name="CTRL_0"> + <bitfield name="CLKSL_SHUTDOWNB" pos="7" type="boolean"/> + <bitfield name="DIGTOP_PWRDN_B" pos="6" type="boolean"/> + <bitfield name="PLL_SHUTDOWNB" pos="5" type="boolean"/> + <bitfield name="DLN3_SHUTDOWNB" pos="4" type="boolean"/> + <bitfield name="DLN2_SHUTDOWNB" pos="3" type="boolean"/> + <bitfield name="CLK_SHUTDOWNB" pos="2" type="boolean"/> + <bitfield name="DLN1_SHUTDOWNB" pos="1" type="boolean"/> + <bitfield name="DLN0_SHUTDOWNB" pos="0" type="boolean"/> + </reg32> <reg32 offset="0x00028" name="CTRL_1"/> <reg32 offset="0x0002c" name="CTRL_2"/> <reg32 offset="0x00030" name="CTRL_3"/> + <reg32 offset="0x001b0" name="CTRL_5"/> <reg32 offset="0x00034" name="LANE_CFG0"/> <reg32 offset="0x00038" name="LANE_CFG1"/> <reg32 offset="0x0003c" name="PLL_CNTRL"/> @@ -183,11 +201,24 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <reg32 offset="0x01b0" name="COMMON_STATUS_ONE"/> <reg32 offset="0x01b4" name="COMMON_STATUS_TWO"/> <reg32 offset="0x01b8" name="BAND_SEL_CAL"/> + <!-- + Starting with SM8750, offset moved from 0x01bc to 0x01cc, however + we keep only one register map. That's not a problem, so far, + because this register is not used. The register map should be split + once it is going to be used. Comment out the code to prevent + any misuse due to the change in the offset. <reg32 offset="0x01bc" name="ICODE_ACCUM_STATUS_LOW"/> + <reg32 offset="0x01cc" name="ICODE_ACCUM_STATUS_LOW"/> + --> <reg32 offset="0x01c0" name="ICODE_ACCUM_STATUS_HIGH"/> <reg32 offset="0x01c4" name="FD_OUT_LOW"/> <reg32 offset="0x01c8" name="FD_OUT_HIGH"/> + <!-- + Starting with SM8750, offset moved from 0x01cc to 0x01bc, however + we keep only one register map. See above comment. <reg32 offset="0x01cc" name="ALOG_OBSV_BUS_STATUS_1"/> + <reg32 offset="0x01bc" name="ALOG_OBSV_BUS_STATUS_1"/> + --> <reg32 offset="0x01d0" name="PLL_MISC_CONFIG"/> <reg32 offset="0x01d4" name="FLL_CONFIG"/> <reg32 offset="0x01d8" name="FLL_FREQ_ACQ_TIME"/> diff --git a/drivers/gpu/drm/msm/registers/display/hdmi.xml b/drivers/gpu/drm/msm/registers/display/hdmi.xml index 1cf1b14fbd91..0ebb96297dae 100644 --- a/drivers/gpu/drm/msm/registers/display/hdmi.xml +++ b/drivers/gpu/drm/msm/registers/display/hdmi.xml @@ -131,7 +131,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> --> <bitfield name="GENERIC0_SEND" pos="0" type="boolean"/> <bitfield name="GENERIC0_CONT" pos="1" type="boolean"/> - <bitfield name="GENERIC0_UPDATE" low="2" high="3" type="uint"/> <!-- ??? --> + <bitfield name="GENERIC0_UPDATE" pos="2" type="boolean"/> <bitfield name="GENERIC1_SEND" pos="4" type="boolean"/> <bitfield name="GENERIC1_CONT" pos="5" type="boolean"/> <bitfield name="GENERIC0_LINE" low="16" high="21" type="uint"/> diff --git a/drivers/gpu/drm/msm/registers/display/mdss.xml b/drivers/gpu/drm/msm/registers/display/mdss.xml index ac85caf1575c..6e9f81cd4690 100644 --- a/drivers/gpu/drm/msm/registers/display/mdss.xml +++ b/drivers/gpu/drm/msm/registers/display/mdss.xml @@ -21,7 +21,16 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <reg32 offset="0x00058" name="UBWC_DEC_HW_VERSION"/> - <reg32 offset="0x00144" name="UBWC_STATIC"/> + <reg32 offset="0x00144" name="UBWC_STATIC"> + <bitfield name="UBWC_SWIZZLE" low="0" high="2"/> + <bitfield name="UBWC_BANK_SPREAD" pos="3"/> + <!-- high=5 for UBWC < 4.0 --> + <bitfield name="HIGHEST_BANK_BIT" low="4" high="6"/> + <bitfield name="UBWC_MIN_ACC_LEN" low="8" high="9"/> + <bitfield name="UBWC_AMSBC" pos="10"/> + <bitfield name="MACROTILE_MODE" pos="12"/> + </reg32> + <reg32 offset="0x00150" name="UBWC_CTRL_2"/> <reg32 offset="0x00154" name="UBWC_PREDICTION_MODE"/> </domain> diff --git a/drivers/gpu/drm/msm/registers/gen_header.py b/drivers/gpu/drm/msm/registers/gen_header.py index 3926485bb197..2acad951f1e2 100644 --- a/drivers/gpu/drm/msm/registers/gen_header.py +++ b/drivers/gpu/drm/msm/registers/gen_header.py @@ -30,7 +30,7 @@ class Enum(object): def names(self): return [n for (n, value) in self.values] - def dump(self): + def dump(self, is_deprecated): use_hex = False for (name, value) in self.values: if value > 0x1000: @@ -44,7 +44,7 @@ class Enum(object): print("\t%s = %d," % (name, value)) print("};\n") - def dump_pack_struct(self): + def dump_pack_struct(self, is_deprecated): pass class Field(object): @@ -69,11 +69,11 @@ class Field(object): raise parser.error("booleans should be 1 bit fields") elif self.type == "float" and not (high - low == 31 or high - low == 15): raise parser.error("floats should be 16 or 32 bit fields") - elif not self.type in builtin_types and not self.type in parser.enums: + elif self.type not in builtin_types and self.type not in parser.enums: raise parser.error("unknown type '%s'" % self.type) def ctype(self, var_name): - if self.type == None: + if self.type is None: type = "uint32_t" val = var_name elif self.type == "boolean": @@ -123,7 +123,7 @@ def field_name(reg, f): name = f.name.lower() else: # We hit this path when a reg is defined with no bitset fields, ie. - # <reg32 offset="0x88db" name="RB_BLIT_DST_ARRAY_PITCH" low="0" high="28" shr="6" type="uint"/> + # <reg32 offset="0x88db" name="RB_RESOLVE_SYSTEM_BUFFER_ARRAY_PITCH" low="0" high="28" shr="6" type="uint"/> name = reg.name.lower() if (name in [ "double", "float", "int" ]) or not (name[0].isalpha()): @@ -145,10 +145,23 @@ def indices_strides(indices): "%s(i%d)" % (offset, idx) for (idx, (ctype, stride, offset)) in enumerate(indices)]) +def is_number(str): + try: + int(str) + return True + except ValueError: + return False + +def sanitize_variant(variant): + if variant and "-" in variant: + return variant[:variant.index("-")] + return variant + class Bitset(object): def __init__(self, name, template): self.name = name self.inline = False + self.reg = None if template: self.fields = template.fields[:] else: @@ -174,18 +187,15 @@ class Bitset(object): print("#endif\n") print(" return (struct fd_reg_pair) {") - if reg.array: - print(" .reg = REG_%s(__i)," % reg.full_name) - else: - print(" .reg = REG_%s," % reg.full_name) - + print(" .reg = (uint32_t)%s," % reg.reg_offset()) print(" .value =") + cast = "(uint64_t)" if reg.bit_size == 64 else "" for f in self.fields: if f.type in [ "address", "waddress" ]: continue else: type, val = f.ctype("fields.%s" % field_name(reg, f)) - print(" (%-40s << %2d) |" % (val, f.low)) + print(" (%s%-40s << %2d) |" % (cast, val, f.low)) value_name = "dword" if reg.bit_size == 64: value_name = "qword" @@ -203,7 +213,7 @@ class Bitset(object): print(" };") - def dump_pack_struct(self, reg=None): + def dump_pack_struct(self, is_deprecated, reg=None): if not reg: return @@ -228,12 +238,15 @@ class Bitset(object): tab_to(" uint32_t", "dword;") print("};\n") + depcrstr = "" + if is_deprecated: + depcrstr = " FD_DEPRECATED" if reg.array: - print("static inline struct fd_reg_pair\npack_%s(uint32_t __i, struct %s fields)\n{" % - (prefix, prefix)) + print("static inline%s struct fd_reg_pair\npack_%s(uint32_t __i, struct %s fields)\n{" % + (depcrstr, prefix, prefix)) else: - print("static inline struct fd_reg_pair\npack_%s(struct %s fields)\n{" % - (prefix, prefix)) + print("static inline%s struct fd_reg_pair\npack_%s(struct %s fields)\n{" % + (depcrstr, prefix, prefix)) self.dump_regpair_builder(reg) @@ -252,28 +265,37 @@ class Bitset(object): (prefix, prefix, prefix, skip)) - def dump(self, prefix=None): - if prefix == None: + def dump(self, is_deprecated, prefix=None, reg=None): + if prefix is None: prefix = self.name + reg64 = reg and self.reg and self.reg.bit_size == 64 + if reg64: + print("static inline uint32_t %s_LO(uint32_t val)\n{" % prefix) + print("\treturn val;\n}") + print("static inline uint32_t %s_HI(uint32_t val)\n{" % prefix) + print("\treturn val;\n}") for f in self.fields: if f.name: name = prefix + "_" + f.name else: name = prefix - if not f.name and f.low == 0 and f.shr == 0 and not f.type in ["float", "fixed", "ufixed"]: + if not f.name and f.low == 0 and f.shr == 0 and f.type not in ["float", "fixed", "ufixed"]: pass - elif f.type == "boolean" or (f.type == None and f.low == f.high): + elif f.type == "boolean" or (f.type is None and f.low == f.high): tab_to("#define %s" % name, "0x%08x" % (1 << f.low)) else: - tab_to("#define %s__MASK" % name, "0x%08x" % mask(f.low, f.high)) + typespec = "ull" if reg64 else "u" + tab_to("#define %s__MASK" % name, "0x%08x%s" % (mask(f.low, f.high), typespec)) tab_to("#define %s__SHIFT" % name, "%d" % f.low) type, val = f.ctype("val") + ret_type = "uint64_t" if reg64 else "uint32_t" + cast = "(uint64_t)" if reg64 else "" - print("static inline uint32_t %s(%s val)\n{" % (name, type)) + print("static inline %s %s(%s val)\n{" % (ret_type, name, type)) if f.shr > 0: print("\tassert(!(val & 0x%x));" % mask(0, f.shr - 1)) - print("\treturn ((%s) << %s__SHIFT) & %s__MASK;\n}" % (val, name, name)) + print("\treturn (%s(%s) << %s__SHIFT) & %s__MASK;\n}" % (cast, val, name, name)) print() class Array(object): @@ -285,6 +307,7 @@ class Array(object): self.domain = domain self.variant = variant self.parent = parent + self.children = [] if self.parent: self.name = self.parent.name + "_" + self.local_name else: @@ -336,12 +359,15 @@ class Array(object): offset += self.parent.total_offset() return offset - def dump(self): + def dump(self, is_deprecated): + depcrstr = "" + if is_deprecated: + depcrstr = " FD_DEPRECATED" proto = indices_varlist(self.indices()) strides = indices_strides(self.indices()) array_offset = self.total_offset() if self.fixed_offsets: - print("static inline uint32_t __offset_%s(%s idx)" % (self.local_name, self.index_ctype())) + print("static inline%s uint32_t __offset_%s(%s idx)" % (depcrstr, self.local_name, self.index_ctype())) print("{\n\tswitch (idx) {") if self.index_type: for val, offset in zip(self.index_type.names(), self.offsets): @@ -356,7 +382,7 @@ class Array(object): else: tab_to("#define REG_%s_%s(%s)" % (self.domain, self.name, proto), "(0x%08x + %s )\n" % (array_offset, strides)) - def dump_pack_struct(self): + def dump_pack_struct(self, is_deprecated): pass def dump_regpair_builder(self): @@ -372,6 +398,7 @@ class Reg(object): self.bit_size = bit_size if array: self.name = array.name + "_" + self.name + array.children.append(self) self.full_name = self.domain + "_" + self.name if "stride" in attrs: self.stride = int(attrs["stride"], 0) @@ -396,25 +423,34 @@ class Reg(object): else: return self.offset - def dump(self): + def reg_offset(self): + if self.array: + offset = self.array.offset + self.offset + return "(0x%08x + 0x%x*__i)" % (offset, self.array.stride) + return "0x%08x" % self.offset + + def dump(self, is_deprecated): + depcrstr = "" + if is_deprecated: + depcrstr = " FD_DEPRECATED " proto = indices_prototype(self.indices()) strides = indices_strides(self.indices()) offset = self.total_offset() if proto == '': tab_to("#define REG_%s" % self.full_name, "0x%08x" % offset) else: - print("static inline uint32_t REG_%s(%s) { return 0x%08x + %s; }" % (self.full_name, proto, offset, strides)) + print("static inline%s uint32_t REG_%s(%s) { return 0x%08x + %s; }" % (depcrstr, self.full_name, proto, offset, strides)) if self.bitset.inline: - self.bitset.dump(self.full_name) + self.bitset.dump(is_deprecated, self.full_name, self) + print("") - def dump_pack_struct(self): + def dump_pack_struct(self, is_deprecated): if self.bitset.inline: - self.bitset.dump_pack_struct(self) + self.bitset.dump_pack_struct(is_deprecated, self) def dump_regpair_builder(self): - if self.bitset.inline: - self.bitset.dump_regpair_builder(self) + self.bitset.dump_regpair_builder(self) def dump_py(self): print("\tREG_%s = 0x%08x" % (self.full_name, self.offset)) @@ -443,9 +479,6 @@ class Parser(object): self.variants = set() self.file = [] self.xml_files = [] - self.copyright_year = None - self.authors = [] - self.license = None def error(self, message): parser, filename = self.stack[-1] @@ -453,7 +486,7 @@ class Parser(object): def prefix(self, variant=None): if self.current_prefix_type == "variant" and variant: - return variant + return sanitize_variant(variant) elif self.current_stripe: return self.current_stripe + "_" + self.current_domain elif self.current_prefix: @@ -499,15 +532,22 @@ class Parser(object): return varset def parse_variants(self, attrs): - if not "variants" in attrs: + if "variants" not in attrs: return None - variant = attrs["variants"].split(",")[0] - if "-" in variant: - variant = variant[:variant.index("-")] + variant = attrs["variants"].split(",")[0] varset = self.parse_varset(attrs) - assert varset.has_name(variant) + if "-" in variant: + # if we have a range, validate that both the start and end + # of the range are valid enums: + start = variant[:variant.index("-")] + end = variant[variant.index("-") + 1:] + assert varset.has_name(start) + if end != "": + assert varset.has_name(end) + else: + assert varset.has_name(variant) return variant @@ -571,9 +611,6 @@ class Parser(object): error_str = str(xmlschema.error_log.filter_from_errors()[0]) raise self.error("Schema validation failed for: " + filename + "\n" + error_str) except ImportError as e: - if self.validate: - raise e - print("lxml not found, skipping validation", file=sys.stderr) def do_parse(self, filename): @@ -619,6 +656,7 @@ class Parser(object): self.current_reg = Reg(attrs, self.prefix(variant), self.current_array, bit_size) self.current_reg.bitset = self.current_bitset + self.current_bitset.reg = self.current_reg if len(self.stack) == 1: self.file.append(self.current_reg) @@ -642,7 +680,7 @@ class Parser(object): elif name == "domain": self.current_domain = attrs["name"] if "prefix" in attrs: - self.current_prefix = self.parse_variants(attrs) + self.current_prefix = sanitize_variant(self.parse_variants(attrs)) self.current_prefix_type = attrs["prefix"] else: self.current_prefix = None @@ -650,7 +688,7 @@ class Parser(object): if "varset" in attrs: self.current_varset = self.enums[attrs["varset"]] elif name == "stripe": - self.current_stripe = self.parse_variants(attrs) + self.current_stripe = sanitize_variant(self.parse_variants(attrs)) elif name == "enum": self.current_enum_value = 0 self.current_enum = Enum(attrs["name"]) @@ -685,10 +723,6 @@ class Parser(object): self.parse_field(attrs["name"], attrs) elif name == "database": self.do_validate(attrs["xsi:schemaLocation"]) - elif name == "copyright": - self.copyright_year = attrs["year"] - elif name == "author": - self.authors.append(attrs["name"] + " <" + attrs["email"] + "> " + attrs["name"]) def end_element(self, name): if name == "domain": @@ -702,11 +736,16 @@ class Parser(object): elif name == "reg32": self.current_reg = None elif name == "array": + # if the array has no Reg children, push an implicit reg32: + if len(self.current_array.children) == 0: + attrs = { + "name": "REG", + "offset": "0", + } + self.parse_reg(attrs, 32) self.current_array = self.current_array.parent elif name == "enum": self.current_enum = None - elif name == "license": - self.license = self.cdata def character_data(self, data): self.cdata += data @@ -719,10 +758,10 @@ class Parser(object): if variants: for variant, vreg in variants.items(): if reg == vreg: - d[(usage, variant)].append(reg) + d[(usage, sanitize_variant(variant))].append(reg) else: for variant in self.variants: - d[(usage, variant)].append(reg) + d[(usage, sanitize_variant(variant))].append(reg) print("#ifdef __cplusplus") @@ -752,6 +791,9 @@ class Parser(object): print("#endif") + def has_variants(self, reg): + return reg.name in self.variant_regs and not is_number(reg.name) and not is_number(reg.name[1:]) + def dump(self): enums = [] bitsets = [] @@ -765,7 +807,7 @@ class Parser(object): regs.append(e) for e in enums + bitsets + regs: - e.dump() + e.dump(self.has_variants(e)) self.dump_reg_usages() @@ -781,8 +823,7 @@ class Parser(object): def dump_reg_variants(self, regname, variants): - # Don't bother for things that only have a single variant: - if len(variants) == 1: + if is_number(regname) or is_number(regname[1:]): return print("#ifdef __cplusplus") print("struct __%s {" % regname) @@ -833,11 +874,20 @@ class Parser(object): xtravar = "__i, " print("__%s(%sstruct __%s fields) {" % (regname, xtra, regname)) for variant in variants.keys(): - print(" if (%s == %s) {" % (varenum.upper(), variant)) + if "-" in variant: + start = variant[:variant.index("-")] + end = variant[variant.index("-") + 1:] + if end != "": + print(" if ((%s >= %s) && (%s <= %s)) {" % (varenum.upper(), start, varenum.upper(), end)) + else: + print(" if (%s >= %s) {" % (varenum.upper(), start)) + else: + print(" if (%s == %s) {" % (varenum.upper(), variant)) reg = variants[variant] reg.dump_regpair_builder() print(" } else") print(" assert(!\"invalid variant\");") + print(" return (struct fd_reg_pair){};") print("}") if bit_size == 64: @@ -850,7 +900,7 @@ class Parser(object): def dump_structs(self): for e in self.file: - e.dump_pack_struct() + e.dump_pack_struct(self.has_variants(e)) for regname in self.variant_regs: self.dump_reg_variants(regname, self.variant_regs[regname]) @@ -867,32 +917,7 @@ def dump_c(args, guard, func): print("#ifndef %s\n#define %s\n" % (guard, guard)) - print("""/* Autogenerated file, DO NOT EDIT manually! - -This file was generated by the rules-ng-ng gen_header.py tool in this git repository: -http://gitlab.freedesktop.org/mesa/mesa/ -git clone https://gitlab.freedesktop.org/mesa/mesa.git - -The rules-ng-ng source files this header was generated from are: -""") - maxlen = 0 - for filepath in p.xml_files: - maxlen = max(maxlen, len(filepath)) - for filepath in p.xml_files: - pad = " " * (maxlen - len(filepath)) - filesize = str(os.path.getsize(filepath)) - filesize = " " * (7 - len(filesize)) + filesize - filetime = time.ctime(os.path.getmtime(filepath)) - print("- " + filepath + pad + " (" + filesize + " bytes, from " + filetime + ")") - if p.copyright_year: - current_year = str(datetime.date.today().year) - print() - print("Copyright (C) %s-%s by the following authors:" % (p.copyright_year, current_year)) - for author in p.authors: - print("- " + author) - if p.license: - print(p.license) - print("*/") + print("/* Autogenerated file, DO NOT EDIT manually! */") print() print("#ifdef __KERNEL__") @@ -910,9 +935,20 @@ The rules-ng-ng source files this header was generated from are: print("#endif") print() + print("#ifndef FD_NO_DEPRECATED_PACK") + print("#define FD_DEPRECATED __attribute__((deprecated))") + print("#else") + print("#define FD_DEPRECATED") + print("#endif") + print() + func(p) - print("\n#endif /* %s */" % guard) + print() + print("#undef FD_DEPRECATED") + print() + + print("#endif /* %s */" % guard) def dump_c_defines(args): @@ -929,7 +965,7 @@ def dump_py_defines(args): p = Parser() try: - p.parse(args.rnn, args.xml) + p.parse(args.rnn, args.xml, args.validate) except Error as e: print(e, file=sys.stderr) exit(1) |
